可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'m working on a simple tool that transfers files to a hard-coded location with the password also hard-coded. I\'m a python novice, but thanks to ftplib, it was easy:
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)
The problem is that I can\'t find any library that supports sFTP. What\'s the normal way to do something like this securely?
Edit: Thanks to the answers here, I\'ve gotten it working with Paramiko and this was the syntax.
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.\'
Thanks again!
回答1:
Paramiko supports SFTP. I\'ve used it, and I\'ve used Twisted. Both have their place, but you might find it easier to start with Paramiko.
回答2:
You should check out pysftp https://pypi.python.org/pypi/pysftp it depends on paramiko, but wraps most common use cases to just a few lines of 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.\'
回答3:
If you want easy and simple, you might also want to look at Fabric. It\'s an automated deployment tool like Ruby\'s Capistrano, but simpler and ofc ourse for Python. It\'s build on top of Paramiko.
You might not want to do \'automated deployment\' but Fabric would suit your use case perfectly none the less. To show you how simple Fabric is: the fab file and command for your script would look like this (not tested, but 99% sure it will work):
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
Then run the file with the fab command:
fab -f fab_putfile.py put_file:file=./path/to/my/file
And you\'re done! :)
回答4:
Here is a sample using pysftp and a private key.
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 is an easy to use sftp module that utilizes paramiko and pycrypto. It provides a simple interface to sftp.. Other things that you can do with pysftp which are quite useful:
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
More commands and about PySFTP here.
回答5:
Twisted can help you with what you are doing, check out their documentation, there are plenty of examples. Also it is a mature product with a big developer/user community behind it.
回答6:
You can use the pexpect module
Here is a good intro post
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\')
I haven\'t tested this but it should work
回答7:
Paramiko is so slow. Use subprocess and shell, here is an example:
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)
回答8:
With RSA Key then refer here
Snippet:
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)
回答9:
There are a bunch of answers that mention pysftp, so in the event that you want a context manager wrapper around pysftp, here is a solution that is even less code that ends up looking like the following when used
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.\")
The (fuller) example: http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
This context manager happens to have auto-retry logic baked in in the event you can\'t connect the first time around (which surprisingly happens more often than you\'d expect in a production environment...)
The context manager gist for open_sftp
: https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515