I'd like to catch nicely the error when "No hostkey for host *** is found" and give an appropriate message to the end user. I tried this:
import pysftp, paramiko
try:
with pysftp.Connection('1.2.3.4', username='root', password='') as sftp:
sftp.listdir()
except paramiko.ssh_exception.SSHException as e:
print('SSH error, you need to add the public key of your remote in your local known_hosts file first.', e)
but unfortunately the output is not very nice:
SSH error, you need to add the public key of your remote in your local known_hosts file first. No hostkey for host 1.2.3.4 found.
Exception ignored in: <function Connection.__del__ at 0x00000000036B6D38>
Traceback (most recent call last):
File "C:\Python37\lib\site-packages\pysftp\__init__.py", line 1013, in __del__
self.close()
File "C:\Python37\lib\site-packages\pysftp\__init__.py", line 784, in close
if self._sftp_live:
AttributeError: 'Connection' object has no attribute '_sftp_live'
How to nicely avoid these last lines / this "exception ignored" with a try: except:
?
The analysis by @reverse_engineer is correct. However:
self._transport
, also is defined too late.pysftp.Connection
class as follows:import pysftp
import paramiko
class My_Connection(pysftp.Connection):
def __init__(self, *args, **kwargs):
self._sftp_live = False
self._transport = None
super().__init__(*args, **kwargs)
try:
with My_Connection('1.2.3.4', username='root', password='') as sftp:
l = sftp.listdir()
print(l)
except paramiko.ssh_exception.SSHException as e:
print('SSH error, you need to add the public key of your remote in your local known_hosts file first.', e)
Update
I could not duplicate this error on my desktop. However, I see in the source for pysftp
in the code where it initializes its _cnopts
attribute with self._cnopts = cnopts or CnOpts()
where cnopts
is a keyword parameter to the pysftp.Connection
constructor and there is a possibilty of the CnOpts
constructor throwing a HostKeysException
exception if no host keys are found resulting in the _cnopts
attribute not being set.
Try the following updated code and let me know if it works:
import pysftp
import paramiko
class My_Connection(pysftp.Connection):
def __init__(self, *args, **kwargs):
try:
if kwargs.get('cnopts') is None:
kwargs['cnopts'] = pysftp.CnOpts()
except pysftp.HostKeysException as e:
self._init_error = True
raise paramiko.ssh_exception.SSHException(str(e))
else:
self._init_error = False
self._sftp_live = False
self._transport = None
super().__init__(*args, **kwargs)
def __del__(self):
if not self._init_error:
self.close()
try:
with My_Connection('1.2.3.4', username='root', password='') as sftp:
l = sftp.listdir()
print(l)
except paramiko.ssh_exception.SSHException as e:
print('SSH error, you need to add the public key of your remote in your local known_hosts file first.', e)
I had the same problem. I solved this by disabling the hostkeys in the cnops:
import pysftp as sftp
FTP_HOST = "sftp.abcd.com"
FTP_USER = "root"
FTP_PASS = ""
cnopts = sftp.CnOpts()
cnopts.hostkeys = None
with sftp.Connection(host=FTP_HOST, username=FTP_USER, password=FTP_PASS, cnopts=cnopts) as sftp:
print("Connection succesfully stablished ... ")
sftp.cwd('/folder/') # Switch to a remote directory
directory_structure = sftp.listdir_attr() # Obtain structure of the remote directory
for attr in directory_structure:
print(attr.filename, attr)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With