Согласно документации transfer.put () , я должен иметь возможность либо указать локальный путь к файлу (в виде строки), либо объект, подобный файлу.
При использовании первого (строки) я могу указать в пути remote
только целевой каталог. Это используется в некоторых примерах :
c.put('myfiles.tgz', '/opt/mydata')
Но когда я пытаюсь сделать то же самое ( c.put('file.txt', '/home/me/dir')
, я всегда получаю IOError: Failure
, потому что на самом деле он ведет себя так, как если бы путь local
был файловым объектом и не строка.
Он не работает специально на 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-сервер открыть каталог как файл для записи вместо привязки базового имени локального файла к пути удаленного каталога.
Частичный журнал отладки со стороны Fabric:
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')
Затем часть трассировки показывает, что мы добавляем этот путь к каталогу в CMD_OPEN, в sftp_client.py
:
t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
Что в конечном итоге затрагивает обработку ошибок того же файла / класса вокруг того, что, по словам SFTP-сервера, было неправильным с операцией ввода-вывода (поэтому это просто «Сбой», потому что, конечно, это ... AFAIK, это ошибка OpenSSH.)
В любом случае, пора написать несколько тестов, чтобы доказать это, а затем выяснить, является ли это логикой (я думал, что в какой-то момент мы _конструировали добавленный путь) или фактически отсутствующим элементом функциональности.
Хорошо, нет, вся эта работа связана с пустыми или относительными удаленными путями, здесь нет проверки is-directory.
Пока я здесь, задаюсь вопросом, как обрабатывать FLO, если удаленный путь - это каталог.
В v1 мы рассмотрели атрибут .name
FLOs, потому что он является частью Python FLO API ..._ но_, по-видимому, только для целей журнала отладки (в # 699). Ой. Я просмотрел наш код и код Paramiko и не увидел ничего, что на самом деле использовало бы это как ключ к "имени файла".
В любом случае, здесь, в версии 2, у нас есть возможность решить эту проблему для вещественных значений или просто выбросить явное исключение, в котором говорится: «Эй, эй, вам нужно указать для них путь к удаленному файлу, не являющийся каталогом». Возможно и то, и другое, поскольку не все FLO в любом случае обязательно имеют атрибут name.
Хорошо, это все исправлено, будет выпущено в следующем выпуске исправлений 🎉