我想在“找不到主机 *** 的主机密钥”时很好地捕获错误,并向最终用户提供适当的消息。我试过这个:
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)
但不幸的是输出不是很好:
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'
try: except:
?
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)
看来附加属性
self._transport
pysftp.Connection
类来实现永久修复,如下所示:
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)
我无法在桌面上重复此错误。但是,我在代码中看到
pysftp
的源代码,它用
_cnopts
初始化其 self._cnopts = cnopts or CnOpts()
属性,其中 cnopts
是 pysftp.Connection
构造函数的关键字参数,并且有可能存在 CnOpts
如果未找到主机密钥,构造函数会抛出 HostKeysException
异常,从而导致未设置 _cnopts
属性。尝试以下更新的代码并让我知道它是否有效:
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)
pysftp.Connection
在
No hostkey for XXX found
异常中失败时,您总是会遇到这种行为,因为失败的 Connection
对象(它失败了,因此您无法访问它,但它存在于 Python 解释器中)会被 GC 清理,它会删除它,正如您在here所看到的,它会首先尝试关闭连接。 我们看到
close()
通过检查
self._sftp_live
来检查连接是否处于活动状态。然而,在定义该属性之前,在 Connection
的构造函数中抛出了异常(异常发生在第 132 行,而
_sftp_live
是在第 134 行定义的),因此将失败的 Connection
对象留在状态不一致,因此会出现未捕获的异常。除了为 pysftp 项目引入一个很好的错误修复之外,我想不出简单的解决方案;) 这对我有用:
import pysftp as sftp
FTP_HOST = "**"
FTP_USER = "****"
FTP_PASS = "rw"
port='34343'
cnopts = sftp.CnOpts()
cnopts.hostkeys = None
with sftp.Connection(host=FTP_HOST, username=FTP_USER, password=FTP_PASS, cnopts=cnopts,port=3333) as sftp:
print("Connection succesfully stablished ... ")
sftp.cwd('jfjksdfjk') # Switch to a remote directory
directory_structure = sftp.listdir_attr()
sftp.get('fd.csv','C:\\windows\\directory\\your_file_name.csv')
for attr in directory_structure:
print(attr.filename, attr)#get all directory