Я работаю над простым инструментом, который передает файлы в жестко запрограммированное место с жестко запрограммированным паролем. Я новичок в питоне, но благодаря ftplib это было легко:
import ftplib
info= ('someuser', 'password') #hard-coded
def putfile(file, site, dir, user=(), verbose=True):
"""
upload a file by ftp to a site/directory
login hard-coded, binary transfer
"""
if verbose: print 'Uploading', file
local = open(file, 'rb')
remote = ftplib.FTP(site)
remote.login(*user)
remote.cwd(dir)
remote.storbinary('STOR ' + file, local, 1024)
remote.quit()
local.close()
if verbose: print 'Upload done.'
if __name__ == '__main__':
site = 'somewhere.com' #hard-coded
dir = './uploads/' #hard-coded
import sys, getpass
putfile(sys.argv[1], site, dir, user=info)
Проблема в том, что я не могу найти ни одной библиотеки, поддерживающей sFTP. Каков нормальный способ сделать что-то подобное безопасным?
Обновлено: благодаря ответам здесь я получил работу с Paramiko, и это был синтаксис.
import paramiko
host = "THEHOST.com" #hard-coded
port = 22
transport = paramiko.Transport((host, port))
password = "THEPASSWORD" #hard-coded
username = "THEUSERNAME" #hard-coded
transport.connect(username = username, password = password)
sftp = paramiko.SFTPClient.from_transport(transport)
import sys
path = './THETARGETDIRECTORY/' + sys.argv[1] #hard-coded
localpath = sys.argv[1]
sftp.put(localpath, path)
sftp.close()
transport.close()
print 'Upload done.'
Еще раз спасибо!
Просто общее замечание по исходному вопросу, что python ftplib также поддерживает FTPS - ftp over TLS en.m.wikipedia.org/wiki/FTPS. Серверы FTPS, возможно, меньше используются в мире Unix, отчасти из-за вездесущности ssh / sftp, однако серверы sftp гораздо меньше присутствуют в среде Windows, где FTPS более распространен.
Похоже, поддержка FTPS была добавлена в Python 3.2 с расширенным классом источник: class ftplib.FTP_TLS (host = '', user = '', passwd = '', acct = '', keyfile = None, certfile = None, context = Нет, тайм-аут = Нет, адрес_источника = Нет)
Я точно следил за этим и получаю ошибку "файл не найден". Я проверил использование os.path.abspath и os.path.isfile, но все еще получаю ошибки при запуске этого скрипта. Что происходит?






Скрученный может помочь вам с тем, что вы делаете, посмотрите их документацию, есть много примеров. Кроме того, это зрелый продукт с большим сообществом разработчиков и пользователей.
Парамико поддерживает SFTP. Я использовал его, и я использовал Twisted. У обоих есть свое место, но, возможно, вам будет проще начать с Парамико.
yepp, paramiko - это путь (очень простой в использовании), немного сложно найти пакет Windows для pycrypto, который является зависимостью.
Спасибо. Мне потребовалось время, чтобы понять, как установить пакет, из-за отсутствия инструкций по установке в readme, но это было именно то, что мне было нужно!
См. bitprophet.org/blog/2012/09/29/paramiko-and-ssh, в котором Джефф Форсьер объясняет, что ssh устарел, а paramiko - это путь вперед.
Также есть code.google.com/p/pysftp, основанный на Paramiko, но более простой в использовании
Обратите внимание, что Paramiko в настоящее время не поддерживает аутентификацию с помощью нескольких методов (например, пароля и закрытого ключа). См. github.com/paramiko/paramiko/issues/519.
также остерегайтесь лицензии ....
Если вам нужно легкое и простое, вы также можете взглянуть на Ткань. Это инструмент автоматического развертывания, подобный Ruby's Capistrano, но более простой и, конечно, для Python. Он построен на Парамико.
Возможно, вы не захотите выполнять «автоматическое развертывание», но, тем не менее, Fabric идеально подойдет для вашего варианта использования. Чтобы показать вам, насколько проста Fabric: файл fab и команда для вашего скрипта будут выглядеть следующим образом (не проверено, но на 99% уверен, что он будет работать):
fab_putfile.py:
from fabric.api import *
env.hosts = ['THEHOST.com']
env.user = 'THEUSER'
env.password = 'THEPASSWORD'
def put_file(file):
put(file, './THETARGETDIRECTORY/') # it's copied into the target directory
Затем запустите файл командой fab:
fab -f fab_putfile.py put_file:file=./path/to/my/file
И вы сделали! :)
Я следил за этим и получил сообщение «Не могу найти коллекцию с именем fabfile!» когда я запускаю файл python.
Вы должны проверить pysftp https://pypi.python.org/pypi/pysftp, он зависит от paramiko, но охватывает наиболее распространенные варианты использования всего несколькими строками кода.
import pysftp
import sys
path = './THETARGETDIRECTORY/' + sys.argv[1] #hard-coded
localpath = sys.argv[1]
host = "THEHOST.com" #hard-coded
password = "THEPASSWORD" #hard-coded
username = "THEUSERNAME" #hard-coded
with pysftp.Connection(host, username=username, password=password) as sftp:
sftp.put(localpath, path)
print 'Upload done.'
Проголосуйте за with в примере
pip install pysftpЕсть ли возможность автоматически добавлять новый хост sftp к известным хостам?
@ user443854 да, есть pysftp.readthedocs.io/en/release_0.2.9/…, но я бы определенно не рекомендовал это, хотя вы можете добавить еще один файл known_host
ВНИМАНИЕ: похоже, что pysftp больше не очень активен. Ссылка на систему отслеживания проблем на их сайте не работает (говорит, что она не настроена). Я обнаружил ошибку и пытаюсь найти лучший способ ее задокументировать и исправить, но не похоже, что она обновлялась более 4 лет.
Вот пример использования pysftp и закрытого ключа.
import pysftp
def upload_file(file_path):
private_key = "~/.ssh/your-key.pem" # can use password keyword in Connection instead
srv = pysftp.Connection(host = "your-host", username = "user-name", private_key=private_key)
srv.chdir('/var/web/public_files/media/uploads') # change directory on remote server
srv.put(file_path) # To download a file, replace put with get
srv.close() # Close connection
pysftp - это простой в использовании модуль sftp, который использует paramiko и pycrypto. Он предоставляет простой интерфейс для sftp .. Другие полезные вещи, которые вы можете делать с помощью pysftp:
data = srv.listdir() # Get the directory and file listing in a list
srv.get(file_path) # Download a file from remote server
srv.execute('pwd') # Execute a command on the server
Еще команды и про PySFTP здесь.
srv.get(file_path) # Download a file from remote server вы можете объяснить где загружает ли он файл?
Вы пробовали местный для вас казненный?
Да, но где в файловой системе? Все проходит успешно, но я не могу найти файл нигде.
Извините, я имел в виду местный реж. Попробуйте выполнить сценарий из домашнего каталога и посмотрите, есть ли там файл.
Существует множество ответов, в которых упоминается pysftp, поэтому, если вам нужна оболочка диспетчера контекста для pysftp, вот решение, в котором еще меньше кода, который при использовании выглядит следующим образом
path = "sftp://user:p@[email protected]/path/to/file.txt"
# Read a file
with open_sftp(path) as f:
s = f.read()
print s
# Write to a file
with open_sftp(path, mode='w') as f:
f.write("Some content.")
Пример (более полный): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
В этот диспетчер контекста встроена логика автоповтора на случай, если вы не можете подключиться в первый раз (что на удивление случается чаще, чем вы ожидаете в производственной среде ...)
Суть диспетчера контекста для open_sftp: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515
Вы можете использовать модуль pexpect
child = pexpect.spawn ('/usr/bin/sftp ' + [email protected] )
child.expect ('.* password:')
child.sendline (your_password)
child.expect ('sftp> ')
child.sendline ('dir')
child.expect ('sftp> ')
file_list = child.before
child.sendline ('bye')
Я не тестировал это, но он должен работать
Парамико такая медлительная. Используйте подпроцесс и оболочку, вот пример:
remote_file_name = "filename"
remotedir = "/remote/dir"
localpath = "/local/file/dir"
ftp_cmd_p = """
#!/bin/sh
lftp -u username,password sftp://ip:port <<EOF
cd {remotedir}
lcd {localpath}
get {filename}
EOF
"""
subprocess.call(ftp_cmd_p.format(remotedir=remotedir,
localpath=localpath,
filename=remote_file_name
),
shell=True, stdout=sys.stdout, stderr=sys.stderr)
Речь идет о «Python», что обычно подразумевает соблюдение этого принципа, особенно когда есть так много вариантов для этого. Что еще более важно, в нем написано «Независимо от платформы». Я не могу сказать, работает ваш ответ быстрее или нет. Возможно?
С RSA Key затем обратитесь к здесь
Фрагмент:
import pysftp
import paramiko
from base64 import decodebytes
keydata = b"""AAAAB3NzaC1yc2EAAAADAQABAAABAQDl"""
key = paramiko.RSAKey(data=decodebytes(keydata))
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add(host, 'ssh-rsa', key)
with pysftp.Connection(host=host, username=username, password=password, cnopts=cnopts) as sftp:
with sftp.cd(directory):
sftp.put(file_to_sent_to_ftp)
PyFilesystem с его sshfs - один из вариантов. Он использует Paramiko под капотом и обеспечивает более приятный независимый интерфейс сверху.
import fs
sf = fs.open_fs("sftp://[user[:password]@]host[:port]/[directory]")
sf.makedir('my_dir')
или же
from fs.sshfs import SSHFS
sf = SSHFS(...
fsspec - отличный вариант для этого, он предлагает файловую систему, подобную реализации sftp.
from fsspec.implementations.sftp import SFTPFileSystem
fs = SFTPFileSystem(host=host, username=username, password=password)
# list a directory
fs.ls("/")
# open a file
with fs.open(file_name) as file:
content = file.read()
Также стоит отметить, что fsspec использует paramiko в выполнение.
Спасибо ! Получил скрипт загрузки SFTP, работающий за 5 минут :)