我正在尝试使用 paramiko 将文件上传到远程 EC2 服务器。
我的 app.py 主要处理我的 tkinter GUI,它导入一个处理某些功能的自定义 lib.file_handler 模块。该 file_handler 导入我的 lib.ssh_handler.py 模块。该模块有一个类可以处理我的 ssh 请求。如果我在 ssh_handler.py 模块中的
if __name__ == '__main__':
中测试我的类,效果很好。我知道这是在导入的模块中产生额外线程的问题,我只是不知道如何解决这个问题,因为这个模块在我的应用程序中是如此深入。 这个线程建议在导入期间不要调用 connect() ,我认为我没有这样做,因为在使用它之前我必须在 lib.file_handler.py 中启动该类。我不想总是连接到远程服务器,只有当我想上传文件时,所以我不想在我的 app.py 中使用 paramiko.connect() 。
问题 104 自 2012 年以来一直开放,但 py3compat 似乎不再是该模块的一部分。
任何有关如何解决此线程问题的意见,或者 paramiko 的良好替代方案,我们将不胜感激。 .
file_handler.py
from lib.ssh_handler import ssh_Handler
ssh = ssh_Handler()
ssh = ssh.upload_files()
ssh_hanlder.py
import paramiko
import lib.Secrets as Secrets
class ssh_Handler():
"""Handle interactions with a remote server"""
def __init__(self, hostname=Secrets.hostname, user=Secrets.ssh_user, ssh_key=Secrets.ssh_key):
self.ssh = paramiko.SSHClient()
self.ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
self.ssh.connect(hostname=hostname, port=22, username=user, key_filename=ssh_key, allow_agent=False)
self.storage_folder = '/path/to/storage'
03-18 14:02 paramiko.transport DEBUG starting thread (client mode): 0xe42de650
03-18 14:02 paramiko.transport DEBUG Local version/idstring: SSH-2.0-paramiko_3.4.0
03-18 14:02 paramiko.transport DEBUG Remote version/idstring: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6
03-18 14:02 paramiko.transport INFO Connected (version 2.0, client OpenSSH_8.9p1)
我最终放弃了 Paramiko,转而使用 asyncssh。工作代码如下。这也让我免于编写递归上传函数。
import asyncio
import asyncssh
async def upload_directory(local_folder,
remote_folder=None,
hostname=Secrets.hostname,
user=Secrets.ssh_user,
ssh_key=Secrets.ssh_key):
if remote_folder is None:
remote_folder = 'folder/to/storage'
async with asyncssh.connect(host=hostname,
username=user,
client_keys=ssh_key,
port=22) as conn:
async with conn.start_sftp_client() as sftp:
await sftp.put(localpaths=local_folder,
remotepath=remote_folder,
recurse=True)
try:
local_path = 'path/to/directory'
asyncio.get_event_loop().run_until_complete(upload_directory(local_path))
except (OSError, asyncssh.Error) as error:
print(error)