Bas*_*asj 18 python sftp exception paramiko pysftp
我想很好地捕获“找不到主机 *** 的主机密钥”时的错误,并向最终用户提供适当的消息。我试过这个:
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)
Run Code Online (Sandbox Code Playgroud)
但不幸的是输出不是很好:
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'
Run Code Online (Sandbox Code Playgroud)
如何很好地避免最后几行/这个“忽略异常” try: except:?
小智 18
我有同样的问题。我通过禁用 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)
Run Code Online (Sandbox Code Playgroud)
rev*_*eer 12
我认为这是 pysftp 中的一个错误。pysftp.Connection当异常失败时,您总是会遇到这种行为No hostkey for XXX found,因为失败的Connection对象(它失败了,所以您无法访问它,但它存在于 Python 解释器中)会被 GC 清理,GC 会删除它,并且您可以看这里,它首先尝试关闭连接。
我们看到通过检查来close() 检查连接是否有效self._sftp_live。但是,在定义该属性之前,在构造函数中抛出了异常Connection(异常发生在第 132 行,而_sftp_live定义在第 134 行),因此导致失败的Connection对象处于不一致的状态,从而导致您看到未捕获的异常。
除了向 pysftp 项目引入一个很好的错误修复之外,我没有想到简单的解决方案;)
Boo*_*boo 12
@reverse_engineer的分析是正确的。然而:
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)
Run Code Online (Sandbox Code Playgroud)
更新
我无法在桌面上重复此错误。但是,我在代码的源代码中看到,pysftp它使用构造函数的关键字_cnopts参数self._cnopts = cnopts or CnOpts()where初始化其属性,并且如果未找到主机密钥,则构造函数有可能抛出异常,从而导致cnoptspysftp.ConnectionCnOptsHostKeysException_cnopts异常,从而导致未设置属性。
尝试以下更新的代码并让我知道它是否有效:
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)
Run Code Online (Sandbox Code Playgroud)