6
__all__ = ("SelectProcess", "ThreadedProcess", "GProcess")
8
def gsignature(*args, **kwargs):
9
run_when = kwargs.pop("run_when", gobject.SIGNAL_RUN_FIRST)
10
return_type = kwargs.pop("return_type", gobject.TYPE_NONE)
11
return (run_when, return_type, args)
13
def read_all_iter(buff, block_size=2048):
14
"""Auxiliar function that reads all data it cans"""
15
chunk = read_some(buff, block_size)
18
while len(chunk) == block_size:
19
chunk = read_some(buff, block_size)
22
def read_all(sock, block_size=2048):
23
return "".join(read_all_iter(sock, block_size))
25
def read_some(buff, block_size=2048):
26
return os.read(buff.fileno(), block_size)
28
class AbstractGProcess(gobject.GObject):
30
"started": gsignature(gobject.TYPE_INT),
31
"finished": gsignature(gobject.TYPE_INT),
32
"stdout-data": gsignature(gobject.TYPE_STRING),
33
"stderr-data": gsignature(gobject.TYPE_STRING),
36
def __init__(self, args):
38
gobject.GObject.__init__(self)
44
if self.proc.poll() is not None:
48
os.kill(self.proc.pid, 15)
51
os.kill(self.proc.pid, 9)
56
def do_finished(self, pid):
59
class PolledProcess(AbstractGProcess):
63
self.proc = subprocess.Popen(
65
stdout=subprocess.PIPE,
66
stderr=subprocess.PIPE,
69
self.emit("started", self.proc.pid)
70
gobject.timeout_add(self.polling_time, self.on_tick)
73
val = self.proc.poll()
75
# TODO: make this smoother, data should be read in
76
# chunks in order to avoid flooding the UI with info
77
self.emit("stdout-data", self.proc.stdout.read())
78
self.emit("stderr-data", self.proc.stderr.read())
79
self.emit("finished", val)
83
class SelectProcess(AbstractGProcess):
86
self.proc = subprocess.Popen(
88
stdout=subprocess.PIPE,
89
stderr=subprocess.PIPE,
92
self._out = gobject.io_add_watch(self.proc.stdout,
93
gobject.IO_IN, self.on_buff_read, "stdout-data")
94
self._err = gobject.io_add_watch(self.proc.stderr,
95
gobject.IO_IN, self.on_buff_read, "stderr-data")
96
gobject.child_watch_add(self.proc.pid, self.on_finished)
97
self.emit("started", self.proc.pid)
99
def on_buff_read(self, fd, cond, signame):
101
self.emit(signame, data)
103
def on_finished(self, pid, condition):
105
gobject.source_remove(self._out)
106
gobject.source_remove(self._err)
107
self.emit('stdout-data', read_all(self.proc.stdout))
108
self.emit('stderr-data', read_all(self.proc.stderr))
109
self.emit("finished", condition / 256)
111
#gobject.idle_add(_delayed_stop)
113
if sys.platform == "win32":
114
GProcess = PolledProcess
116
GProcess = SelectProcess
118
if __name__ == '__main__':
121
def on_read(proc, data):
124
def on_finished(obj, err):
129
gproc = PolledProcess
132
proc = gproc(sys.argv[1:])
134
proc.connect("finished", on_finished)
135
proc.connect("stdout-data", on_read)
136
proc.connect("stderr-data", on_read)