Я ищу решение Python, которое позволит мне сохранять вывод команды в файле, не скрывая его от консоли.
К вашему сведению: я спрашиваю о мишени (как утилита командной строки Unix) а не функция с тем же именем от модуля межинструментов Python.
tee
, это не доступно в соответствии с Windows),stderr
и stdout
stderr = subprocess.STDOUT
не будет работать.Вот некоторые неполные решения, которые я нашел до сих пор:
Схема http://blog.i18n.ro/wp-content/uploads/2010/06/Drawing_tee_py.png
#!/usr/bin/python
from __future__ import print_function
import sys, os, time, subprocess, io, threading
cmd = "python -E test_output.py"
from threading import Thread
class StreamThread ( Thread ):
def __init__(self, buffer):
Thread.__init__(self)
self.buffer = buffer
def run ( self ):
while 1:
line = self.buffer.readline()
print(line,end="")
sys.stdout.flush()
if line == '':
break
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdoutThread = StreamThread(io.TextIOWrapper(proc.stdout))
stderrThread = StreamThread(io.TextIOWrapper(proc.stderr))
stdoutThread.start()
stderrThread.start()
proc.communicate()
stdoutThread.join()
stderrThread.join()
print("--done--")
#### test_output.py ####
#!/usr/bin/python
from __future__ import print_function
import sys, os, time
for i in range(0, 10):
if i%2:
print("stderr %s" % i, file=sys.stderr)
else:
print("stdout %s" % i, file=sys.stdout)
time.sleep(0.1)
Реальный вывод
stderr 1
stdout 0
stderr 3
stdout 2
stderr 5
stdout 4
stderr 7
stdout 6
stderr 9
stdout 8
--done--
Ожидаемому выводу состоял в том, чтобы заказать строки. Комментарий, изменяя Popen для использования только одного КАНАЛА не позволяется, потому что в реальной жизни я захочу сделать разные вещи с stderr и stdout.
Также даже во втором случае я не смог получить в реальном времени как, на самом деле все результаты были получены когда законченный процесс. По умолчанию Popen не должен использовать буферы (bufsize=0).
Это - то, как это может быть сделано
import sys
from subprocess import Popen, PIPE
with open('log.log', 'w') as log:
proc = Popen(["ping", "google.com"], stdout=PIPE, encoding='utf-8')
while proc.poll() is None:
text = proc.stdout.readline()
log.write(text)
sys.stdout.write(text)
Мое решение не изящно, но оно работает.
можно использовать powershell для получения доступа для "кладения для первого удара" под WinOS.
import subprocess
import sys
cmd = ['powershell', 'ping', 'google.com', '|', 'tee', '-a', 'log.txt']
if 'darwin' in sys.platform:
cmd.remove('powershell')
p = subprocess.Popen(cmd)
p.wait()