SFTP em Python? (plataforma independente)

Estou a trabalhar numa ferramenta simples que transfere ficheiros para um local codificado com a senha também codificada. Sou um novato em python, mas graças ao ftplib, foi fácil.
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)

o problema é que não consigo encontrar nenhuma biblioteca que suporte o sFTP. Qual é a maneira normal de fazer algo assim de forma segura?

[[3]}Edit: graças às respostas aqui, eu consegui trabalhar com Paramiko e esta foi a sintaxe.

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.'
Obrigado mais uma vez!

 154
Author: Mark Wilbur, 2009-01-11

9 answers

Paramiko suporta o SFTP. Eu usei-o, e usei o Twisted. Ambos têm o seu lugar, mas talvez seja mais fácil começar com a Paramiko.

 96
Author: Brian Clapper, 2009-01-11 05:04:22

Devias ver o pysftp https://pypi.python.org/pypi/pysftp depende de paramiko, mas envolve os casos de uso mais comuns a apenas algumas linhas de código.

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.'
 55
Author: Dundee MT, 2017-08-18 07:56:55

Se você quer fácil e simples, você também pode querer olhar paraTecido . É uma ferramenta de implantação automatizada como o Capistrano de Ruby, mas mais simples e ofc ourse para Python. É construído em cima da Paramiko.

Pode não querer fazer "implantação automatizada", mas o tecido adequava-se perfeitamente à sua mala de uso. Para lhe mostrar o quão simples é o tecido: o ficheiro fab e o comando para o seu programa ficaria assim (não testado, mas 99% de certeza que irá trabalho):

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

Depois execute o ficheiro com o comando fab:

fab -f fab_putfile.py put_file:file=./path/to/my/file
E acabou-se! :)
 15
Author: hopla, 2018-03-09 14:21:04

Aqui está uma amostra usando o pysftp e uma chave privada.

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 é um módulo sftp fácil de usar que utiliza paramiko e pycrypto. Ele fornece uma interface simples para sftp.. Outras coisas que você pode fazer com o pysftp que são bastante úteis:

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

Mais Comandos e sobre o PySFTP aqui.

 8
Author: radtek, 2014-06-06 14:56:58

Twisted pode ajudá-lo com o que está a fazer, Verifique a documentação deles, existem muitos exemplos. Também é um produto maduro com uma grande comunidade de desenvolvedores/usuários por trás dele.

 3
Author: Sergey Golovchenko, 2009-01-11 05:01:24

Pode usar o Módulo pexpect

Aqui está um bom post de Introdução

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')
Ainda não testei isto, mas deve funcionar.
 1
Author: MIkee, 2017-02-20 05:33:36
A Paramiko é tão lenta. Usar subprocesso e shell, aqui está um exemplo:
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
Author: 杨李思, 2017-09-14 03:55:52

Com a chave RSA, consulte então aqui

Excerto:

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
Author: Abhijeet, 2017-10-27 08:29:15

Há um monte de respostas que mencionam o pysftp, por isso, no caso de você querer um pacote de Gerenciador de contexto em torno do pysftp, aqui está uma solução que é ainda menos código que acaba parecendo o seguinte quando usado

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.") 

O exemplo (mais completo): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html

Acontece que este gestor de contexto tem a lógica de auto-repetição cozida no caso de não se conseguir ligar pela primeira vez (o que surpreendentemente acontece mais vezes do que seria de esperar num ambiente de produção...)

O Gestor de contexto gist para open_sftp: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515

 0
Author: prschmid, 2016-11-28 22:41:46