如何在Python中从Shell获取变量?
我正在写一个脚本,需要通过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']
>>>