SFTP в Python? (платформа незалежна)


181

Я працюю над простим інструментом, який передає файли в жорстко закодоване місце з паролем, також жорстко закодованим. Я початківець пітон, але завдяки 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. Який нормальний спосіб зробити таке подібне надійно?

Редагувати: Завдяки відповідям тут я отримав це, працюючи з Параміко, і це був синтаксис.

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
Дякую ! Отримав сценарій завантаження SFTP за 5 хвилин :)
Охад Шнайдер

1
Лише загальна примітка щодо оригінального питання про те, що python ftplib також підтримує FTPS - ftp над TLS en.m.wikipedia.org/wiki/FTPS . Сервери FTPS, мабуть, менше використовуються у світі Unix, частково через всюдисутність ssh / sftp, однак сервери sftp набагато рідше представлені в середовищі Windows, де FTPS є більш поширеним.
Gnudiff

Схоже, підтримка FTPS була додана в Python 3.2 із розширеним джерелом класу : клас ftplib.FTP_TLS (host = '', user = '', passwd = '', acct = '', keyfile = None, certfile = None, контекст = None, timeout = None, source_address = None)
mgrollins

Відповіді:


109

Параміко підтримує SFTP. Я користувався ним, і я використовував Twisted. В обох є своє місце, але вам може бути легше почати з Параміко.


2
yepp, paramiko - це шлях (надзвичайно простий у використанні), його трохи складно знайти пакет Windows pycrypto, який є залежністю.
Mauli

Дякую. Мені знадобилось певний час, щоб зрозуміти, як встановити пакет через відсутність інструкцій щодо встановлення в readme, але це було саме те, що мені потрібно!
Марк Уілбур

15
Див. Bitprophet.org/blog/2012/09/29/paramiko-and-ssh, в якому Джефф Форсьє пояснює, що ssh застаріло, а параміко - це шлях вперед.
Крістофер Махан

2
Також є code.google.com/p/pysftp, який базується на Paramiko, але простіший у використанні
franzlorenzon


78

Ви повинні перевірити 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.'

4
Проголосуйте за withприклад
Роман Подлінов

2
pip install pysftp
Боб Штейн

2
Чи є можливість автоматично додати новий хост sftp до відомих хостів?
user443854

1
@ user443854 так, є pysftp.readthedocs.io/en/release_0.2.9/… Але я точно не рекомендував би цього, хоча ви можете додати ще один відомий файл
AsTeR

15

Якщо ви хочете легко і просто, ви можете також подивитися на тканину . Це автоматизований інструмент розгортання, як 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

І ви закінчили! :)


12

Ось зразок із використанням 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 модуль, який використовує параміко та 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 тут .


srv.get(file_path) # Download a file from remote serverВи можете пояснити, куди він завантажує файл?
Маркус Месканен

Ви спробували локальну для вас страту?
radtek

Так, але де у файловій системі? Все проходить успішно, але я не можу знайти файл з будь-якого місця.
Маркус Месканен

Вибачте, я мав на увазі місцевого реж. Спробуйте виконати сценарій з вашого домашнього редактора і побачити, чи файл там є.
radtek

3

Скручені можуть допомогти вам у тому, що ви робите, ознайомтеся з їх документацією, є чимало прикладів. Крім того, це зрілий продукт із великим спільнотою розробників / користувачів.



1

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

0

Існує маса відповідей, в яких згадується 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


0

Параміко такий повільний. Використовуйте підпроцес та оболонку, ось приклад:

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)

Питання стосується "Python", що, як правило, передбачає дотримання цього - особливо, коли існує так багато варіантів для цього. Що ще важливіше, це говорить, що "Платформа незалежна". Я не можу сказати, чи працює ваша відповідь швидше чи ні. Можливо?
BuvinJ

0

PyFilesystem з його sshfs є одним із варіантів. Він використовує Paramiko під кришкою і забезпечує приємніший незалежний інтерфейс, що відповідає формі.

import fs

sf = fs.open_fs("sftp://[user[:password]@]host[:port]/[directory]")
sf.makedir('my_dir')

або

from fs.sshfs import SSHFS
sf = SSHFS(...

-1

Можна використовувати модуль 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')

Я цього не перевіряв, але це має працювати

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.