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.'

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

Ответ 1

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

Ответ 2

Вы должны проверить 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.'

Ответ 3

Если вы хотите легко и просто, вы также можете посмотреть на ткани. Это инструмент автоматического развертывания, такой как Ruby 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 copied into the target directory

Затем запустите файл с помощью команды fab:

fab -f fab_putfile.py put_file:file=./path/to/my/file

И вы сделали! :)

Ответ 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 здесь.

Ответ 6

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

Ответ 7

Вы можете использовать pexpect module

Вот хороший вводный пост

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')

Я не тестировал это, но он должен работать

Ответ 8

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

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)

Ответ 9

С помощью RSA Key, пожалуйста, напишите здесь

Отрывок:

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)

Ответ 10

Есть несколько ответов, в которых упоминается pysftp, поэтому в случае, если вы хотите, чтобы обертка менеджера контекста вокруг pysftp, это решение, которое еще меньше кода, которое выглядит следующим образом при использовании

path = "sftp://user:[email protected]@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