SFTP в Python? (независимая платформа) - PullRequest
165 голосов
/ 11 января 2009

Я работаю над простым инструментом, который переносит файлы в жестко запрограммированную папку с паролем. Я новичок в 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.'

Еще раз спасибо!

Ответы [ 9 ]

101 голосов
/ 11 января 2009

Paramiko поддерживает SFTP. Я использовал это, и я использовал Twisted. Оба имеют свое место, но вам может быть легче начать с Paramiko.

58 голосов
/ 28 мая 2014

Вы должны проверить 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.'
15 голосов
/ 08 декабря 2009

Если вы хотите легко и просто, вы также можете посмотреть на Fabric . Это инструмент автоматического развертывания, такой как Ruby Capistrano, но более простой и, конечно, для Python. Он построен на основе Paramiko.

Возможно, вы не захотите выполнять «автоматическое развертывание», но 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

И все готово! :)

8 голосов
/ 06 июня 2014

Вот пример использования 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 здесь .

3 голосов
/ 11 января 2009

Twisted может помочь вам с тем, что вы делаете, посмотрите их документацию, есть множество примеров Также это зрелый продукт, за которым стоит большое сообщество разработчиков и пользователей.

1 голос
/ 27 октября 2017

С ключом 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)
1 голос
/ 13 сентября 2017

Парамико такой медленный. Используйте подпроцесс и оболочку, вот пример:

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)
1 голос
/ 20 февраля 2017

Вы можете использовать модуль 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')

Я не проверял это, но оно должно работать

0 голосов
/ 29 ноября 2016

Существует множество ответов, в которых упоминается 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

...