Chức năng glib.spawn_async cho phép bạn móc ba cuộc gọi lại được gọi trên sự kiện trên stdout
, stderr
và hoàn tất quá trình.Bắt chước glib.spawn_async với Popen…
Làm cách nào tôi có thể bắt chước cùng một chức năng với subprocess bằng một trong hai chủ đề hoặc asyncio?
Tôi quan tâm nhiều hơn đến chức năng hơn là luồng/asynio nhưng câu trả lời chứa cả hai sẽ kiếm được tiền thưởng.
Dưới đây là một chương trình đồ chơi cho thấy những gì tôi muốn làm:
import glib
import logging
import os
import gtk
class MySpawn(object):
def __init__(self):
self._logger = logging.getLogger(self.__class__.__name__)
def execute(self, cmd, on_done, on_stdout, on_stderr):
self.pid, self.idin, self.idout, self.iderr = \
glib.spawn_async(cmd,
flags=glib.SPAWN_DO_NOT_REAP_CHILD,
standard_output=True,
standard_error=True)
fout = os.fdopen(self.idout, "r")
ferr = os.fdopen(self.iderr, "r")
glib.child_watch_add(self.pid, on_done)
glib.io_add_watch(fout, glib.IO_IN, on_stdout)
glib.io_add_watch(ferr, glib.IO_IN, on_stderr)
return self.pid
if __name__ == '__main__':
logging.basicConfig(format='%(thread)d %(levelname)s: %(message)s',
level=logging.DEBUG)
cmd = '/usr/bin/git ls-remote https://github.com/DiffSK/configobj'.split()
def on_done(pid, retval, *args):
logging.info("That's all folks!…")
def on_stdout(fobj, cond):
"""This blocks which is fine for this toy example…"""
for line in fobj.readlines():
logging.info(line.strip())
return True
def on_stderr(fobj, cond):
"""This blocks which is fine for this toy example…"""
for line in fobj.readlines():
logging.error(line.strip())
return True
runner = MySpawn()
runner.execute(cmd, on_done, on_stdout, on_stderr)
try:
gtk.main()
except KeyboardInterrupt:
print('')
tôi nên thêm rằng kể từ khi readlines()
được ngăn chặn, bên trên sẽ đệm tất cả các đầu ra và gửi nó cùng một lúc. Nếu đây không phải là điều bạn muốn, thì bạn phải sử dụng readline()
và đảm bảo rằng khi kết thúc lệnh, bạn đọc xong tất cả các dòng bạn chưa đọc trước đó.
Cảm ơn bạn đã dành thời gian viết câu trả lời này. – Sardathrion
Lưu ý rằng ở trên sẽ đệm các dòng trong 'stdout' và' stderr' như 'readlines()' đang chặn. Nếu bạn muốn cập nhật khi nó xảy ra, hãy sử dụng 'read()' nhưng chắc chắn rằng bạn làm trống bộ đệm khi các luồng của trình đọc kết thúc. – Sardathrion