Ratha
Ratha

Reputation: 9692

Python pysftp download fails with "IOError: [Errno 21] Is a directory"

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?

Upvotes: 1

Views: 2556

Answers (2)

Imperishable Night
Imperishable Night

Reputation: 1533

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.

Upvotes: 2

blhsing
blhsing

Reputation: 106553

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)

Upvotes: 2

Related Questions