【问题标题】:How to pass object as commandline argument in python?如何在python中将对象作为命令行参数传递?
【发布时间】:2016-02-27 03:37:29
【问题描述】:

我有一个在 linux 服务器上运行的 python 实例。我使用全局类创建了一个全局数组。我想将此类的对象作为命令行参数传递给我将在 Windows VM 上运行的 python 函数。如何在 python 中将对象作为命令行参数传递? 或者有什么更好的方法吗?

【问题讨论】:

  • 我们在这里讨论的是什么对象?一个序列化的泛型对象,还是 Python 的 string/int/dict/... 字面量作为字符串?
  • @cdarke 从技术上讲,您可以对命令行参数进行编码,然后取消腌制,但是是的...
  • “或者有什么更好的方法吗?” 有更好的方法吗?您要解决的问题是什么?
  • 对象是什么?它代表什么?
  • 我有一个 globalVars() 类,我用它使用 get() 和 set() 方法初始化一些全局变量,这样我就可以在我的文件结构中的任何模块中使用这些变量,只需创建一个该类的对象。现在我想将该对象传递给另一个 Python 实例,该实例将在 Windows VM CMD 上运行。(基本上我想将所有这些变量传递给 Windows VM)。附:我是 Python 新手,所以我可能在这里遗漏了一些概念 :)

标签: python python-2.7 python-3.x


【解决方案1】:

您可以为此使用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

但是,我认为最好在 VM 中运行任务执行服务器。虽然这些服务器选项的主要重点是允许可扩展性,但它们在远程方面也相当出色。这抽象出了所有的通信和序列化解决方案,就像@J.F.塞巴斯蒂安说,你真的不需要重新发明。

Celery 可能是最常用的任务执行服务器库。设置需要一些工作,但配置后使用起来很简单:使用 Celery 装饰器标记您的函数以使其成为任务对象,在 VM 上启动工作程序,导入模块,并使用相同的参数调用类方法您将传递给函数本身。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 您确实可以通过命令行传递此类数据,但需要使用 shlex.quote() 之类的方式对其进行转义。
【解决方案2】:

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

multiprocessing module from stdlib 支持此用例。 Jupyter 支持远程内核。这是使用execnet的代码示例。

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

【讨论】:

    猜你喜欢
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 2015-12-22
    • 2010-11-12
    • 2012-03-12
    • 2020-02-22
    相关资源
    最近更新 更多