transfer.put()のドキュメントによると、ファイルへのローカルパス(文字列として)またはファイルのようなオブジェクトのいずれかを提供できるはずです。
前者(文字列)を使用する場合、 remote
パスにターゲットディレクトリのみを指定できます。 これはいくつかの例で使用されてい
c.put('myfiles.tgz', '/opt/mydata')
しかし、同じことをしようとすると( c.put('file.txt', '/home/me/dir')
、 local
パスがファイルのようなオブジェクトであるかのように実際に動作するため、常にIOError: Failure
になります。文字列ではありません。
特にparamiko.transport.sftp.sftp._log: [chan 0] open('/home/me/dir', 'wb')
で失敗します
解決策は、常にフルパスを提供することです。
c.put('file.txt', '/home/me/dir/file.txt')
しかし、それはドキュメントや例と矛盾しています。
最後に、 $HOME
へのフルパスを提供する必要があることは理想的とは言えませんが、すでに#1653に問題があるようです。
これに関する更新はありますか? Connection.put
とremote
をディレクトリパス文字列として使用すると、現在IOError
ます。
(Fabric他のすべての作業にも感謝します!)
ファブリック2.1.3
パラミコ2.4.1
1.0.0を呼び出す
正当なバグのように聞こえますが、後で調べます。 パッチ(そしてテスト!私たちのすべてが合格したので:(私たちがいくつか欠けていることを意味します...)歓迎します。
これを今見てみると、問題がFLOの想定であるかどうかは実際にはわかりません。代わりに、正しいリモートパス変更を実装していないだけだと思います。つまり、SFTPサーバーにディレクトリを開くように要求しています。ローカルファイルのベース名をリモートディレクトリパスに追加する代わりに、書き込むファイル。
ファブリック側からの部分的なデバッグログ:
invoke.transfer.put: Massaged relative local path 'setup.py' into '/Users/jforcier/Code/oss/fabric/setup.py'
invoke.transfer.put: Uploading '/Users/jforcier/Code/oss/fabric/setup.py' to '/Users/jforcier/tmp/'
paramiko.transport.sftp.sftp._log: [chan 2] open(b'/Users/jforcier/tmp/', 'wb')
次に、トレースバックの一部は、そのディレクトリパスをsftp_client.py
CMD_OPENにスローしていることを示しています。
t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
これは最終的に、SFTPサーバーがIO操作で間違っていると言ったことに関する同じファイル/クラスのエラー処理にヒットします(これが、OpenSSHの障害であるAFAIKであるため、単に「失敗」である理由です)。
とにかく、これを証明するためにいくつかのテストを書いて、それが論理的なおっと(ある時点で追加されたパスを構築していると思った)なのか、それとも実際に欠けている機能の一部なのかを理解する時が来ました。
OK、いいえ、すべての変更は空のパスまたは相対的なリモートパスの周りにあり、is-directoryチェックはありません。
私がここにいる間、リモートパスがディレクトリである場合、FLOもどのように処理するのか疑問に思います。
v1では、FLOの.name
属性を調べました。これはPython FLO APIの
とにかく、ここv2では、実際にこれに対処するか、「これらのディレクトリ以外のリモートファイルパスを指定する必要があります」という明示的な例外をスローする機会があります。 とにかくすべてのFLOが必ずしもname属性を持っているわけではないので、おそらく両方です。
OK、それはすべて修正されました、次のバグ修正リリースで出ます🎉