如何在Python中从Shell获取变量?

1 投票
3 回答
5001 浏览
提问于 2025-04-17 04:06

我正在写一个脚本,需要通过Linux机器上的本地dbus来利用一个Java守护进程。这个守护进程会返回一个元组数组,我想要这个数组,以便在我的代码中解析和使用这些信息。我希望这段代码能够同时从多台机器获取这个值,但问题是,我发现唯一能从我通过SSH连接的终端获取返回值的方法,就是解析标准输出(stdout)的内容。我不想这样做,我更希望能直接获取实际的变量。现在我有这样的代码:

import os
message = "import dbus, sys\nbus=dbus.SystemBus()\nremote_object=bus.get_object('daemon.location', '/daemon')\ncontroller=dbus.Interface(remote_object, 'daemon.path')\nsys.exit(controller.getValue())"
x = os.system('echo \-e "%s" \| ssh %s python' %(message, ip))

在这个例子中,当我运行“controller.getValue()”时,它会返回一个元组数组。我正在想办法获取这个数组。当使用像popen这样的方式时,它会把标准输出的内容导入到一个文件中,然后返回给你,这样你得到的只是这个数组的字符串形式。我想弄明白的是,如何才能获取到实际的数组。就像是把SSH会话退出时返回的变量传递到我的代码中。有什么想法吗?

3 个回答

0

如果你只是想要一个 shell 变量,你可以这样做:

$ FOO="myFOO"
$ export FOO
$ cat x.py
#!/usr/bin/python
import os
print os.environ['FOO']
$ ./x.py
myFOO
$ 

如果你想要一个程序的返回代码:

try:
    retcode = call("mycmd" + " myarg", shell=True)
    if retcode < 0:
        print >>sys.stderr, "Child was terminated by signal", -retcode
    else:
        print >>sys.stderr, "Child returned", retcode
except OSError, e:
    print >>sys.stderr, "Execution failed:", e

如果你能更清楚地说明你的需求,可能会得到更好的帮助。

0

为什么不使用popen?

lines = os.popen("your command here").readlines()
1

如果没有共享内存,你就无法避免序列化。网络上传输的只有字节数据。

你可以使用一些库来帮你处理这些,比如 execnet 模块,这样你就不用自己去处理了:

#!/usr/bin/env python
import execnet

gw = execnet.makegateway("ssh=user@host")
channel = gw.remote_exec("""
import dbus, sys

bus = dbus.SystemBus()
remote_object = bus.get_object('daemon.location', '/daemon')
controller = dbus.Interface(remote_object, 'daemon.path')

channel.send(controller.getValue())
""")
tuple_ = channel.receive()
print tuple_
print tuple_[0]

不过,你也可以自己轻松解析简单的元组值,使用标准库中的 ast.literal_eval() 就可以做到:

#fabfile.py
import ast
from fabric.api import run

def getcontroller():
    """Return controller value."""
    cmd = """
import dbus, sys

bus = dbus.SystemBus()
remote_object = bus.get_object('daemon.location', '/daemon')
controller = dbus.Interface(remote_object, 'daemon.path')

print repr(controller.getValue())
""" #NOTE: you must escape all quotation marks
    output = run('python -c "%s"' % cmd)
    tuple_ = ast.literal_eval(output)
    print tuple_[0]

举个例子: $ fab getcontroller -H user@host

在这里,我使用了 fabric 来在远程主机上运行这个命令。

如果对方不生成 Python 字面量,你可以使用 JSON 作为序列化格式:

>>> import json
>>> t = (1, "a")
>>> json.dumps(t)
'[1, "a"]'
>>> json.loads(_)
[1, u'a']
>>>

撰写回答