基于ssh的Python多处理类执行



查看python的多处理文档页面中的基本示例:

from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
with Pool(5) as p:
print(p.map(f, [1, 2, 3]))

这将在自动启动的单独进程中执行f,但在本地机器上。

我看到它支持远程执行,但这需要手动启动管理器,并且看起来仅支持网络(即在SSH之外,不支持例如stdin/stdout序列化或其他类型的东西)。

是否有一种方法可以通过SSH自动在远程主机上调用python函数(而不是可执行文件,例如使用paramiko.client.SSHClient.exec_command) ?通过"automatically"我的意思是不需要手动处理进程的启动/停止和通信(输入参数和返回值的序列化)。

下面的代码是我如何使用多线程池并发执行多个远程命令的示例。下面的command1显示了我将如何调用远程Python函数。请注意,可能需要Python解释器的完整路径(除非它在您的主目录中),因为通常的环境path变量在之后没有设置。Bash_profile脚本尚未执行。

调用foo的返回值是"printed"因此将是函数connect_and_execute_command返回的stdout输出响应。根据定义,这将是一个字符串。如果foo返回的类型是内置类型,例如int字典包含其值的内置类型,则该类型的字符串表示形式可以转换回其"真实"类型。使用ast.literal_eval.

import paramiko
from multiprocessing.pool import ThreadPool
from ast import literal_eval
def execute_command(client, command):
"""
Execute a command with client, which is already connect to some host.
"""
stdin_, stdout_, stderr_ = client.exec_command(command)
return [stdout_.read().decode(), stderr_.read().decode()]
def connect(hostname, username, password=None):
client = paramiko.client.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
client.connect(hostname=hostname, username=username, password=password)
return client
def connect_and_execute_command(command, hostname, username, password=None):
with connect(hostname, username) as client:
return execute_command(client, command)
command0, host0, user0, password0 = 'ls -l', 'some_host0', 'some_username0', 'some_password0'
command1, host1, user1, password1 = '''~/my_local_python/python -c "from temp import foo; print(foo(6), end='')"''', 'some_host1', 'some_username0', 'some_password1'
requests = ((command0, host0, user0, password0), (command1, host1, user1, password1))
with ThreadPool(len(requests)) as pool:
results = pool.starmap(connect_and_execute_command, requests)
# Convert stdout response from command1:
results[1][0] = literal_eval(results[1][0])
for stdout_response, _ in results:
print(stdout_response, end='')
print()

最新更新