SFTP в Python?(не зависит от платформы)
Вопрос
Я работаю над простым инструментом, который переносит файлы в жестко заданное местоположение с также жестко заданным паролем.Я новичок в python, но благодаря 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.'
Еще раз спасибо!
Решение
Paramiko поддерживает SFTP. Я использовал это, и я использовал Twisted. Оба имеют свое место, но вам может быть легче начать с Paramiko.
Другие советы
Вы должны проверить 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.'
Если вы хотите легко и незатейливо, вы также можете взглянуть на Ткань.Это инструмент автоматического развертывания, подобный Ruby's Capistrano, но более простой и, конечно, для Python.Он построен на вершине Парамико.
Возможно, вы не захотите выполнять "автоматическое развертывание", но, тем не менее, 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
И все готово!:)
Вот пример использования 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 здесь .
Twisted может помочь вам в том, что вы делаете, ознакомьтесь с их документацией, есть множество примеров , Также это зрелый продукт, за которым стоит большое сообщество разработчиков и пользователей. Р>
Вы можете использовать модуль pexpect
Вот хорошее введение разместить р>
child = pexpect.spawn ('/usr/bin/sftp ' + user@ftp.site.com )
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)
С помощью ключа RSA затем обратитесь к здесь
Фрагмент текста:
import pysftp
import paramiko
from base64 import decodebytes
keydata = b"""L+WsiL5VL51ecJi3LVjmblkAdUTU+xbmXmUArIU5+8N6ua76jO/+T"""
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)
Существует множество ответов, в которых упоминается pysftp, поэтому в случае, если вам нужна оболочка диспетчера контекста для pysftp, вот решение, в котором код становится еще меньше, и при использовании он выглядит следующим образом
path = "sftp://user:p@ssw0rd@test.com/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