如何从python内部运行bash脚本并获取所有输出?

问题描述 投票:0回答:2

这是对here中答案的直接澄清问题,我认为它是可行的,但无效!

我有以下测试bash脚本(testbash.sh),它仅创建一些输出和很多错误以进行测试

export MAX_SEED=2
echo "Start test"
pids=""

for seed in `seq 1 ${MAX_SEED}`
do
  python -c "raise ValueError('test')" &
  pids="${pids} $!"
done
echo "pids: ${pids}"
wait $pids
echo "End test"

如果运行此脚本,将得到以下输出:

Start test
pids:  68322 68323
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ValueError: test
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ValueError: test
[1]-  Exit 1                  python -c "raise ValueError('test')"
[2]+  Exit 1                  python -c "raise ValueError('test')"
End test

这是预期的结果。那也行。我想得到错误!

现在是应该捕获所有输出的python代码:

from __future__ import print_function

import sys
import time
from subprocess import PIPE, Popen, STDOUT
from threading  import Thread

try:
    from queue import Queue, Empty
except ImportError:
    from Queue import Queue, Empty  # python 2.x    

ON_POSIX = 'posix' in sys.builtin_module_names

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line.decode('ascii'))
    out.close()

p = Popen(['. testbash.sh'], stdout=PIPE, stderr=STDOUT, bufsize=1, close_fds=ON_POSIX, shell=True)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True # thread dies with the program
t.start()

# read line without blocking
while t.is_alive():
    #time.sleep(1)
    try:
        line = q.get(timeout=.1)
    except Empty:
        print(line)
        pass
    else:
        # got line
        print(line, end='')

p.wait()
print('returncode = {}'.format(p.returncode))

但是当我运行这段代码时,我只会得到以下输出:

Start test
pids:  70191 70192
Traceback (most recent call last):
returncode = 0

上面的大多数输出​​都丢失了!我怎样才能解决这个问题?

有没有更简单的方法来获取从python启动的bash脚本的输出,而bash脚本本身会启动python脚本(是的,我知道,它看起来确实很重要,但是必须像jenkins那样进行涉及,食等)

python bash queue subprocess
2个回答
0
投票

只是猜测-可能是因为您的逻辑未将以空字符/空格开头的行识别为一行。

也许这是问题所在。另一个选择是,有一个选项卡或类似的标签,而ascii解码可能会失败。


0
投票

这是我通常使用子流程的方式:

import subprocess

with subprocess.Popen(["./test.sh"], shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) as p:
    error = p.stderr.read().decode()
    std_out = p.stdout.read().decode()
    if std_out:
        print(std_out)
    if error:
        print("Error message: {}".format(error))

这里您解码并读取标准输出和标准错误。您可以得到所有东西,但顺序不同,如果有问题,我不会。

© www.soinside.com 2019 - 2024. All rights reserved.