Запускать несколько строк bash в Python и отдельно проверять их состояние и вывод - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь выполнить несколько строк bash в Python 3 и проверить статус каждой строки отдельно.

Сначала я попытался использовать gestatusoutput из subprocess, но каждая строка запускается в отдельном процессе, который не связывается с другими (для простоты данный MWE состоит из установки переменной, но что Я намерен сделать в моем действительном коде более сложную задачу - и я знаю о os.environ для этого очень конкретного примера):

from subprocess import getstatusoutput as cmd

stat, out = cmd("export TEST=1")
stat, out = cmd("echo $TEST")

поэтому вернет:

>>> print(out)
(0, "")

Затем я попробовал следующее:

cmdline = """export TEST=1
echo $TEST"""
stat, out = cmd(cmdline)

Это работает, но вынуждает меня анализировать выходные данные, особенно если я хочу проверить состояние первой команды (если echo работает, состояние возвращается cmd равно 0, что бы ни происходило раньше), то есть не очень крепкий.

Я видел некоторые вещи, используя Popen (все еще с subprocess), но не смог использовать его эффективно.

Буду признателен за любую помощь!

Ответы [ 2 ]

0 голосов
/ 08 марта 2019

Я сделал следующее:

  • создайте launch перенос команды subprocess.Popen для запуска команд bash, что дополнительно позволяет мне либо извлечь текущую среду, либо передать пользовательскую среду
  • создать get_env для анализа возврата предыдущей команды и получить dict окружения

launch Обертка

import os
import subprocess as sp

def launch(cmd_, env=os.environ, get_env=False):
    if get_env: cmd_ += " && printenv"
    load = sp.Popen(cmd_, shell=True, stdout=sp.PIPE, stderr=sp.PIPE, env=env)
    out  = load.communicate()
    err  = load.returncode
    return(err, out)

Извлечение окружающей среды

def get_env(out, encoding='utf-8'):
    lout = str(out[0], encoding).split('\n')
    new_env = {}
    for line in lout:
        if len(line.split('=')) <= 1:
            pass
        else:
            k = line.split("=")[0]
            v = "=".join(line.split("=")[1:])
            new_env[k] = v
    return new_env

(Это простая версия, она может быть более сложной, если в вашей среде есть такие вещи, как функции - такое бывает.)


Результаты:

Я могу использовать его следующим образом:

err, out = launch("export TEST=1", get_env=True)
if not err: new_env = get_env(out)
err, out = launch("echo $TEST", env=new_env)

и, следовательно:

>>> print(str(out[0], encoding='utf-8'))
1
0 голосов
/ 24 января 2019

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

Process 1 python main.py                #TEST = "" 
    |Process 2-->"export TEST=1"        #Change Process2 env variable TEST to '1'
    |Process 3-->"echo $TEST"           #Print Process3 env variable TEST (get from process 1)

Вы можете использовать os.environ [], чтобы сначала изменить текущую среду (переменная процесса 1), Позже использовать переменную после fork.

Что-то вродеэто

import os
import subprocess
import sys

os.environ['TEST'] = '1'
out = subprocess.check_call('echo $TEST',shell = True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...