如何在Python中将对象作为命令行参数传递?

4
我在一个Linux服务器上运行了一个Python实例。我已经使用global类创建了一个全局数组。我想要将这个类的对象作为命令行参数传递给我在Windows虚拟机上运行的Python函数。我该如何在Python中将对象作为命令行参数传递?或者有更好的方法吗?

我们在谈论哪些对象?是序列化的通用对象,还是Python字符串/整数/字典等文字形式的字面量? - timgeb
@cdarke,从技术上讲,您可以对命令行参数进行编码,然后再进行反序列化,但是...... - timgeb
1
“还有更好的方法吗?”做什么?你试图解决什么问题? - mzjn
什么是对象?它代表什么? - Tom Dalton
变量是什么类型的对象?这很重要。如果它们只是内置对象,如字典、列表、字符串和整数,那么你比传递其他对象时更容易实现。 - pydsigner
显示剩余2条评论
2个回答

3

您可以使用json.dumps()json.loads()pickle.dumps()pickle.loads()来实现此目的:

>>> import json
>>> json.dumps(['Hi'])
'["Hi"]'
>>> json.loads(_)
['Hi']

>>> import pickle
>>> pickle.dumps(['Hi'])
b'\x80\x03]q\x00X\x02\x00\x00\x00Hiq\x01a.'
>>> pickle.loads(_)
['Hi']

请注意,如果您尝试传递一个特殊类,则需要进行一些额外的工作; 您需要有功能来转换JSON格式,1而pickle将自动执行操作,但仍需要访问该类。2 然而,我认为你最好在虚拟机中运行任务执行服务器。虽然这些服务器选项的主要重点是允许可扩展性,但它们在远程方面也非常出色。这将抽象掉所有通信和序列化解决方案,正如@J.F. Sebastian所说,您真的不需要重新发明。
Celery可能是最常用的任务执行服务器库。设置需要一些工作,但配置后使用起来很简单:使用Celery装饰器标记函数以使其成为任务对象,在VM上启动worker,导入模块,并调用具有与函数本身相同参数的类方法。3一旦一切正常,Celery工作者可以设置为Windows服务。4
# app.py (adapted from examples in the Celery Getting Started tutorial
from celery import Celery

app = Celery('tasks', broker='amqp://guest@localhost//')

@app.task
def my_function(a, b):
    return a * b


# main.py
import app

result = app.my_function.delay(4, 5)
print result.get()

有时候,Celery可能会让人感到麻烦。如果您需要在函数中使用第三方库,则必须在函数中导入它们或在Linux服务器上安装它们,这是由于Celery的直观排列所致。而且我个人也曾经遇到过Celery的设置问题。
一种更简单的选择是TaskIt。5(全部披露:我是TaskIt的开发人员)。它使用更传统的服务器-客户端连接样式,因此只需要正常的TCP套接字即可。默认情况下,它使用JSON序列化对象,但也支持pickle。
# server.py
from taskit.backend import BackEnd

def my_function(a, b):
    return a * b

backend = BackEnd(dict(my_function=my_function))
backend.main()


# client.py
from taskit.frontend import FrontEnd

backend_addr = '127.0.0.1'
frontend = FrontEnd([backend_addr])
print frontend.work('my_function', 4, 5)

你不能直接将pickle或json的输出发送到bash命令行,因为bash使用的格式与其他格式不同,所以你几乎肯定会收到无效命令错误。 - Cerin
@Cerin 你确实可以通过命令行传递这样的数据,但它需要使用像shlex.quote()这样的东西进行转义。 - pydsigner

0

使用任何你想用的方法,在运行在不同计算机上的进程之间进行通信。

multiprocessing标准库模块支持这种用例。Jupyter支持远程内核。以下是一个使用execnet的代码示例。

如果你首先将对象序列化为字符串,那么可以将对象作为命令行参数传递。但是没有必要创建另一种远程执行Python代码的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接