问题
Here is my sample Python script where I want to download a file from SFTP server to my local.
srv = pysftp.Connection(host=host, username=username, password=password, port=port, cnopts=connOption)
with srv.cd(sftppath):
data = srv.listdir()
try:
for infile in data:
print infile
srv.get(infile, destination, preserve_mtime=True)
I can connect successfully and it lists all files in the folder. But when I use srv.get()
to download to my desktop I get following error,
IOError: [Errno 21] Is a directory: '/Users/ratha/Desktop'
Error stack;
Traceback (most recent call last):
File "/Users/ratha/PycharmProjects/SFTPDownloader/handler.py", line 9, in <module>
main()
File "/Users/ratha/PycharmProjects/SFTPDownloader/handler.py", line 5, in main
downloadSFTPFiles()
File "/Users/ratha/PycharmProjects/SFTPDownloader/Utilities/SFTPConnector.py", line 49, in downloadSFTPFiles
srv.get(infile, destination, preserve_mtime=True)
File "/Users/ratha/PycharmProjects/SFTPDownloader/venv/lib/python2.7/site-packages/pysftp/__init__.py", line 249, in get
self._sftp.get(remotepath, localpath, callback=callback)
File "/Users/ratha/PycharmProjects/SFTPDownloader/venv/lib/python2.7/site-packages/paramiko/sftp_client.py", line 801, in get
with open(localpath, "wb") as fl:
IOError: [Errno 21] Is a directory: '/Users/ratha/Desktop'
What Im doing wrong here?
回答1:
The stack trace is actually really clear. Just focus on these two lines:
with open(localpath, "wb") as fl:
IOError: [Errno 21] Is a directory: '/Users/ratha/Desktop'
Clearly, pysftp
tries to open /Users/ratha/Desktop
as a file for binary write, which didn't go well because that is already, well, a directory. The documentation will confirm this:
localpath (str) – the local path and filename to copy, destination. If not specified, file is copied to local current working directory
Therefore you need to figure out the file name you want to save as, and use (best practice) os.path.join('/Users/ratha/Desktop', filename)
to get a path and filename, instead of just a path.
回答2:
Your destination
variable should hold the path to the target file, with the file name included. If the target file name is to be the same as the source file name, you can join the base name of the source file name with the target directory instead:
import os
...
srv.get(infile, os.path.join(destination, os.path.basename(infile)), preserve_mtime=True)
来源:https://stackoverflow.com/questions/56746767/python-pysftp-download-fails-with-ioerror-errno-21-is-a-directory