pipedprocess.py
74 lines
| 2.5 KiB
| text/x-python
|
PythonLexer
Gael Varoquaux
|
r1437 | # encoding: utf-8 | ||
""" | ||||
Bernardo B. Marques
|
r4872 | Object for encapsulating process execution by using callbacks for stdout, | ||
Gael Varoquaux
|
r1437 | stderr and stdin. | ||
""" | ||||
__docformat__ = "restructuredtext en" | ||||
#------------------------------------------------------------------------------- | ||||
# Copyright (C) 2008 The IPython Development Team | ||||
# | ||||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#------------------------------------------------------------------------------- | ||||
#------------------------------------------------------------------------------- | ||||
# Imports | ||||
#------------------------------------------------------------------------------- | ||||
gvaroquaux
|
r1455 | from killableprocess import Popen, PIPE | ||
Gael Varoquaux
|
r1437 | from threading import Thread | ||
Gael Varoquaux
|
r1439 | from time import sleep | ||
Gael Varoquaux
|
r1506 | import os | ||
Gael Varoquaux
|
r1437 | |||
class PipedProcess(Thread): | ||||
Gael Varoquaux
|
r1457 | """ Class that encapsulates process execution by using callbacks for | ||
stdout, stderr and stdin, and providing a reliable way of | ||||
killing it. | ||||
""" | ||||
Gael Varoquaux
|
r1437 | |||
Bernardo B. Marques
|
r4872 | def __init__(self, command_string, out_callback, | ||
Gael Varoquaux
|
r1437 | end_callback=None,): | ||
Gael Varoquaux
|
r1457 | """ command_string: the command line executed to start the | ||
Bernardo B. Marques
|
r4872 | process. | ||
Gael Varoquaux
|
r1457 | |||
out_callback: the python callable called on stdout/stderr. | ||||
end_callback: an optional callable called when the process | ||||
finishes. | ||||
These callbacks are called from a different thread as the | ||||
thread from which is started. | ||||
""" | ||||
Gael Varoquaux
|
r1437 | self.command_string = command_string | ||
self.out_callback = out_callback | ||||
self.end_callback = end_callback | ||||
Thread.__init__(self) | ||||
Bernardo B. Marques
|
r4872 | |||
Gael Varoquaux
|
r1437 | |||
def run(self): | ||||
""" Start the process and hook up the callbacks. | ||||
""" | ||||
Gael Varoquaux
|
r1506 | env = os.environ | ||
env['TERM'] = 'xterm' | ||||
gvaroquaux
|
r1662 | process = Popen(self.command_string + ' 2>&1', shell=True, | ||
Gael Varoquaux
|
r1506 | env=env, | ||
Gael Varoquaux
|
r1437 | universal_newlines=True, | ||
Gael Varoquaux
|
r1450 | stdout=PIPE, stdin=PIPE, ) | ||
Gael Varoquaux
|
r1437 | self.process = process | ||
while True: | ||||
out_char = process.stdout.read(1) | ||||
Gael Varoquaux
|
r1439 | if out_char == '': | ||
if process.poll() is not None: | ||||
# The process has finished | ||||
break | ||||
else: | ||||
# The process is not giving any interesting | ||||
# output. No use polling it immediatly. | ||||
sleep(0.1) | ||||
else: | ||||
self.out_callback(out_char) | ||||
Gael Varoquaux
|
r1437 | |||
if self.end_callback is not None: | ||||
self.end_callback() | ||||
Bernardo B. Marques
|
r4872 | |||
Gael Varoquaux
|
r1437 | |||