web-dev-qa-db-fra.com

SFTP en Python? (indépendant de la plateforme)

Je travaille sur un outil simple qui transfère des fichiers vers un emplacement codé en dur avec le mot de passe également codé en dur. Je suis un novice python, mais grâce à ftplib, c'était facile:

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 __== '__main__':
    site = 'somewhere.com'            #hard-coded
    dir = './uploads/'                #hard-coded
    import sys, getpass
    putfile(sys.argv[1], site, dir, user=info)

Le problème est que je ne trouve aucune bibliothèque prenant en charge sFTP. Quelle est la façon normale de faire quelque chose comme ça en toute sécurité?

Edit: Merci aux réponses ici, je l’ai obtenu avec Paramiko et c’était la syntaxe.

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

Merci encore!

166
Mark Wilbur

Paramiko supporte SFTP. Je l'ai utilisé et j'ai utilisé Twisted. Les deux ont leur place, mais vous trouverez peut-être plus facile de commencer avec Paramiko.

102
Brian Clapper

Vous devriez vérifier pysftp https://pypi.python.org/pypi/pysftp cela dépend de paramiko, mais résume les cas d'utilisation les plus courants à quelques lignes de code.

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.'
62
Dundee MT

Si vous voulez facile et simple, vous pouvez également regarder Fabric . C'est un outil de déploiement automatisé comme Capistrano de Ruby, mais plus simple et bien sûr pour Python. Il est construit sur Paramiko.

Vous ne voudrez peut-être pas faire de "déploiement automatisé", mais Fabric conviendrait néanmoins parfaitement à votre cas d'utilisation. Pour vous montrer à quel point Fabric est simple: le fichier fab et la commande de votre script ressemblent à ceci (non testé, mais il est sûr à 99% que cela fonctionnera):

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

Puis exécutez le fichier avec la commande fab:

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

Et tu as fini! :)

15
hopla

Voici un exemple utilisant pysftp et une clé privée.

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 est un module sftp facile à utiliser utilisant paramiko et pycrypto. Il fournit une interface simple à sftp .. Voici d'autres choses que vous pouvez faire avec pysftp et qui sont très utiles:

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

Plus de commandes et à propos de PySFTP here .

8
radtek

Twisted peut vous aider avec ce que vous faites, consultez leur documentation, il existe de nombreux exemples. C'est aussi un produit mature avec une grande communauté de développeurs/utilisateurs.

3
Sergey Golovchenko

Avec RSA Key, reportez-vous à ici

Fragment:

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
Abhijeet

Paramiko est si lent. Utilisez sous-processus et Shell, voici un exemple:

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
杨李思

Vous pouvez utiliser le module pexpect

Voici un bon post d’intro

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

Je n'ai pas testé cela mais ça devrait marcher

1
MIkee

Il y a un tas de réponses qui mentionnent pysftp, donc dans le cas où vous voulez un gestionnaire de contexte autour de pysftp, voici une solution qui contient encore moins de code et qui ressemble finalement à ce qui suit lorsqu'elle est utilisée

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

L'exemple (le plus complet): http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html

Il arrive que ce gestionnaire de contexte ait une logique de nouvelle tentative intégrée si vous ne pouvez pas vous connecter la première fois (ce qui est surprenant plus souvent que prévu dans un environnement de production ...).

Le gestionnaire de contexte Gist for open_sftp: https://Gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515

0
prschmid