Как получить переменную из оболочки в python? - PullRequest
1 голос
/ 11 октября 2011

Я пишу скрипт, который должен использовать демон Java через локальный dbus машин linux, на которых он будет работать. Этот демон, в частности, вернет массив кортежей, которые я хочу, чтобы я мог позже проанализировать / использовать информацию в моем коде. Я хочу, чтобы этот код получал это значение сразу с нескольких машин, но проблема в том, что единственный способ получить значения возврата / выхода с терминала, в который я помещаю 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 он передает вывод в stdout в файл и возвращает его вам, таким образом вы получаете строковый эквивалент массива. Я пытаюсь понять, как получить реальный массив. Как будто передать переменную, возвращаемую при выходе из SSH TTY в мой код. Есть идеи?

Ответы [ 3 ]

1 голос
/ 12 октября 2011

Нельзя избежать сериализации, если нет общей памяти. На проводе есть только байты. Вы можете использовать библиотеку, которая скрывает это от вас, например, с 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() из 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 user@host

Здесь я использовал fabric для запуска команды на удаленном хосте.

Вы можете использовать JSON в качестве формата сериализации, если на другом конце не создаются литералы Python:

>>> import json
>>> t = (1, "a")
>>> json.dumps(t)
'[1, "a"]'
>>> json.loads(_)
[1, u'a']
>>>
0 голосов
/ 11 октября 2011

Если вам нужна переменная оболочки, вы можете сделать это

$ 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 голосов
/ 11 октября 2011

Почему бы не использовать popen?

lines = os.popen("your command here").readlines()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...