Search code examples
pythonsftpparamiko

sftp file transfer using python works fine despite this ImportError. How to remove this error?


I have this python function to upload file through sftp. It works fine.

def sftp_upload(destination, username, password,
                     remote_loc, source_file):
    import pysftp
    with pysftp.Connection(destination, username,
                           password, log="pysftp.log") as sftp:
        sftp.cwd(remote_loc)
        sftp.put(source_file)

    sftp.close()
    return None

The code works as expected. However, I always receive this error at the end ImportError: sys.meta_path is None, Python is likely shutting down.

How to remove this error? I'm also puzzled why code runs smoothly to the end despite the error.

In the log file, I saw the following;

INF [20220304-18:49:14.727] thr=2   paramiko.transport.sftp: [chan 0] sftp session closed.
DEB [20220304-18:49:14.727] thr=2   paramiko.transport: [chan 0] EOF sent (0)
DEB [20220304-18:49:14.728] thr=1   paramiko.transport: EOF in transport thread

Here's the stack trace;

Exception ignored in: <function Connection.__del__ at 0x000001A8B08765E0>
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\site-packages\pysftp\__init__.py", line 1013, in __del__
  File "C:\ProgramData\Anaconda3\lib\site-packages\pysftp\__init__.py", line 795, in close
ImportError: sys.meta_path is None, Python is likely shutting down

I am using python v3.9


Solution

  • Note: import pysftp outside the function somehow resolves the issue for me. 🤔


    It's a bug in pysftp==0.2.9.

    You can fix it by overriding close() to only run once:

    class SFTPConnection(pysftp.Connection):
        def close(self):
            if getattr(self, '_closed', False):
                return
            self._closed = True
            super().close()
    

    Usage:

    # with pysftp.Connection(destination, username, password=password, log="pysftp.log") as sftp:  # -
    with SFTPConnection(destination, username, password=password, log="pysftp.log") as sftp:       # +
    

    References: