2011-10-11 14 views
1

我正在編寫一個腳本,需要通過它將運行的Linux機器的本地dbus來利用Java守護進程。這個守護進程特別會返回一個我想要的元組數組,這樣我就可以在後面的代碼中解析/使用這些信息。我希望這段代碼能夠同時從多臺機器上獲取這個值,但問題是我真正需要從終端返回/退出值的唯一方式是我通過解析stdout的輸出。我不想這樣做,我更願意獲得實際的變量。現在我有這個:如何從python的shell中獲取變量?

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 tty時返回的變量傳遞給我的代碼。有任何想法嗎?

+0

這正是外殼做:解析輸出,並把它變成變量。沒辦法避免它。 –

回答

1

你不能避免序列如果沒有共享內存。線上只有字節。 你可以用它從你如隱藏它一個庫,execnet模塊:

#!/usr/bin/env python 
import execnet 

gw = execnet.makegateway("[email protected]") 
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()從STDLIB簡單的元組值:

#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 [email protected]

這裏我用fabric在遠程主機上運行命令。

你可以使用JSON作爲一個序列化格式,如果另一端不產生Python的文字:

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

啊,非常感謝!這正是我所期待的。 – SuperFamousGuy

0

爲什麼不使用popen?

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

這就是我所說的我正在試圖避免的。它解析tty中stdout的輸出。 os.popen將stdout的值傳遞給它返回給你的文件對象。我試圖讓我的守護進程返回變量。 – SuperFamousGuy

+0

由於涉及多個進程和機器,這可能有點棘手。由於每個進程都會將狀態返回給父進程,並且父進程必須將其傳回。 爲什麼解析popen的輸出如此糟糕? – Richie

+0

因爲它會使潛在的O(1)最壞情況O(log(n))到O(n)的效率下降。這不是世界上最糟糕的事情。我只是想知道是否有更好的方法。這似乎應該是可能的事情之一,但我不知道該怎麼做。 – SuperFamousGuy

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

對不起,如果我有點模糊,我編輯我的帖子,嘗試更清晰。看起來你的代碼要麼在shell中運行它,要麼將shell輸出解析爲一個變量。我試圖做一些相反的事情,因爲我試圖從shell中獲取一個變量(在本例中是一個數組)。 – SuperFamousGuy