Paramiko SSHClient.connect(...) 在 Windows 上与 Pyinstaller 打包时失败

Paramiko SSHClient.connect(...) fails when packaged with Pyinstaller on Windows

Paramiko 的 SSHClient.connect(...) 方法在使用 Pyinstaller 打包时会引发异常,但在不打包时会 运行 正常。

这会使用 Pyinstaller 标志 --onedir--onefile。我已经尝试了 Pyinstaller 版本 3.5 和当前最新的开发版本 4.0.dev0+ce887b462--noupx 没有明显的效果。

我的 Paramiko 版本是 2.6.0

我当前的 Python 版本是 2.7.15

我的 OS 是 Windows 10 Pro,版本 10.0.17134,内部版本 17134。

这个问题似乎是由于 Paramiko 在 kernel32.dll 中调用 C 函数造成的,意外地 returns null 只有在打包时才如此。

最小示例:

import paramiko

# The nature of this issue unfortunately requires
# a server that responds to SSH connections to test
host = None  # Put a valid hostname here
port = 22  # Put a valid port here

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
    hostname=host,
    port=port,
    username=None,
    password=None,
    timeout=5
)

我希望 Pyinstaller 打包版本 运行 与未打包版本完全相同——在这种情况下,启动 SSH 连接,然后失败并出现 AuthenticationException,因为 usernamepasswordNone:

> virtualenv venv
> venv\Scripts\activate.bat
> pip install pyinstaller==3.5 paramiko==2.6.0
[output truncated for brevity]
> pyinstaller minimal-paramiko-example.py
[output truncated for brevity]
> dist\minimal-paramiko-example\minimal-paramiko-example.exe
Traceback (most recent call last):
  File "minimal-paramiko-example.py", line 16, in <module>
    timeout=5
  File "site-packages\paramiko\client.py", line 446, in connect
  File "site-packages\paramiko\client.py", line 691, in _auth
  File "site-packages\paramiko\agent.py", line 379, in __init__
  File "site-packages\paramiko\agent.py", line 65, in _connect
  File "site-packages\paramiko\agent.py", line 82, in _send_message
  File "site-packages\paramiko\win_pageant.py", line 129, in send
  File "site-packages\paramiko\win_pageant.py", line 96, in _query_pageant
  File "site-packages\paramiko\_winapi.py", line 179, in write
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
[16768] Failed to execute script minimal-paramiko-example

> python minimal-paramiko-example.py  # Will result in an AuthenticationException, since username and password are None; this is expected and normal
[output truncated for brevity]

此问题是由与 PuTTY Pageant 交互引起的。关闭 PuTTY Pageant 不会导致此错误发生。出于某种原因,它只出现在以下极端情况下:

  • 使用 Pyinstaller
  • 运行 PuTTY 选美

不满足这两个要求不会触发问题。