这是对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那样进行涉及,食等)
只是猜测-可能是因为您的逻辑未将以空字符/空格开头的行识别为一行。
也许这是问题所在。另一个选择是,有一个选项卡或类似的标签,而ascii解码可能会失败。
这是我通常使用子流程的方式:
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))
这里您解码并读取标准输出和标准错误。您可以得到所有东西,但顺序不同,如果有问题,我不会。