* morituri/extern (added):
* morituri/extern/__init__.py (added): * morituri/extern/asyncsub.py (added): Add extern module; add asynchronous subprocess Popen from http://code.activestate.com/recipes/440554/
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
2009-04-19 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/extern (added):
|
||||
* morituri/extern/__init__.py (added):
|
||||
* morituri/extern/asyncsub.py (added):
|
||||
Add extern module; add asynchronous subprocess Popen from
|
||||
http://code.activestate.com/recipes/440554/
|
||||
|
||||
2009-04-15 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* examples/gtkchecksum.py:
|
||||
|
||||
0
morituri/extern/__init__.py
vendored
Normal file
0
morituri/extern/__init__.py
vendored
Normal file
168
morituri/extern/asyncsub.py
vendored
Normal file
168
morituri/extern/asyncsub.py
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
# -*- Mode: Python -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
# from http://code.activestate.com/recipes/440554/
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import errno
|
||||
import time
|
||||
import sys
|
||||
|
||||
PIPE = subprocess.PIPE
|
||||
|
||||
if subprocess.mswindows:
|
||||
from win32file import ReadFile, WriteFile
|
||||
from win32pipe import PeekNamedPipe
|
||||
import msvcrt
|
||||
else:
|
||||
import select
|
||||
import fcntl
|
||||
|
||||
class Popen(subprocess.Popen):
|
||||
def recv(self, maxsize=None):
|
||||
return self._recv('stdout', maxsize)
|
||||
|
||||
def recv_err(self, maxsize=None):
|
||||
return self._recv('stderr', maxsize)
|
||||
|
||||
def send_recv(self, input='', maxsize=None):
|
||||
return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
|
||||
|
||||
def get_conn_maxsize(self, which, maxsize):
|
||||
if maxsize is None:
|
||||
maxsize = 1024
|
||||
elif maxsize < 1:
|
||||
maxsize = 1
|
||||
return getattr(self, which), maxsize
|
||||
|
||||
def _close(self, which):
|
||||
getattr(self, which).close()
|
||||
setattr(self, which, None)
|
||||
|
||||
if subprocess.mswindows:
|
||||
def send(self, input):
|
||||
if not self.stdin:
|
||||
return None
|
||||
|
||||
try:
|
||||
x = msvcrt.get_osfhandle(self.stdin.fileno())
|
||||
(errCode, written) = WriteFile(x, input)
|
||||
except ValueError:
|
||||
return self._close('stdin')
|
||||
except (subprocess.pywintypes.error, Exception), why:
|
||||
if why[0] in (109, errno.ESHUTDOWN):
|
||||
return self._close('stdin')
|
||||
raise
|
||||
|
||||
return written
|
||||
|
||||
def _recv(self, which, maxsize):
|
||||
conn, maxsize = self.get_conn_maxsize(which, maxsize)
|
||||
if conn is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
x = msvcrt.get_osfhandle(conn.fileno())
|
||||
(read, nAvail, nMessage) = PeekNamedPipe(x, 0)
|
||||
if maxsize < nAvail:
|
||||
nAvail = maxsize
|
||||
if nAvail > 0:
|
||||
(errCode, read) = ReadFile(x, nAvail, None)
|
||||
except ValueError:
|
||||
return self._close(which)
|
||||
except (subprocess.pywintypes.error, Exception), why:
|
||||
if why[0] in (109, errno.ESHUTDOWN):
|
||||
return self._close(which)
|
||||
raise
|
||||
|
||||
if self.universal_newlines:
|
||||
read = self._translate_newlines(read)
|
||||
return read
|
||||
|
||||
else:
|
||||
def send(self, input):
|
||||
if not self.stdin:
|
||||
return None
|
||||
|
||||
if not select.select([], [self.stdin], [], 0)[1]:
|
||||
return 0
|
||||
|
||||
try:
|
||||
written = os.write(self.stdin.fileno(), input)
|
||||
except OSError, why:
|
||||
if why[0] == errno.EPIPE: #broken pipe
|
||||
return self._close('stdin')
|
||||
raise
|
||||
|
||||
return written
|
||||
|
||||
def _recv(self, which, maxsize):
|
||||
conn, maxsize = self.get_conn_maxsize(which, maxsize)
|
||||
if conn is None:
|
||||
return None
|
||||
|
||||
flags = fcntl.fcntl(conn, fcntl.F_GETFL)
|
||||
if not conn.closed:
|
||||
fcntl.fcntl(conn, fcntl.F_SETFL, flags| os.O_NONBLOCK)
|
||||
|
||||
try:
|
||||
if not select.select([conn], [], [], 0)[0]:
|
||||
return ''
|
||||
|
||||
r = conn.read(maxsize)
|
||||
if not r:
|
||||
return self._close(which)
|
||||
|
||||
if self.universal_newlines:
|
||||
r = self._translate_newlines(r)
|
||||
return r
|
||||
finally:
|
||||
if not conn.closed:
|
||||
fcntl.fcntl(conn, fcntl.F_SETFL, flags)
|
||||
|
||||
message = "Other end disconnected!"
|
||||
|
||||
def recv_some(p, t=.1, e=1, tr=5, stderr=0):
|
||||
if tr < 1:
|
||||
tr = 1
|
||||
x = time.time()+t
|
||||
y = []
|
||||
r = ''
|
||||
pr = p.recv
|
||||
if stderr:
|
||||
pr = p.recv_err
|
||||
while time.time() < x or r:
|
||||
r = pr()
|
||||
if r is None:
|
||||
if e:
|
||||
raise Exception(message)
|
||||
else:
|
||||
break
|
||||
elif r:
|
||||
y.append(r)
|
||||
else:
|
||||
time.sleep(max((x-time.time())/tr, 0))
|
||||
return ''.join(y)
|
||||
|
||||
def send_all(p, data):
|
||||
while len(data):
|
||||
sent = p.send(data)
|
||||
if sent is None:
|
||||
raise Exception(message)
|
||||
data = buffer(data, sent)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.platform == 'win32':
|
||||
shell, commands, tail = ('cmd', ('dir /w', 'echo HELLO WORLD'), '\r\n')
|
||||
else:
|
||||
shell, commands, tail = ('sh', ('ls', 'echo HELLO WORLD'), '\n')
|
||||
|
||||
a = Popen(shell, stdin=PIPE, stdout=PIPE)
|
||||
print recv_some(a),
|
||||
for cmd in commands:
|
||||
send_all(a, cmd + tail)
|
||||
print recv_some(a),
|
||||
send_all(a, 'exit' + tail)
|
||||
print recv_some(a, e=0)
|
||||
a.wait()
|
||||
Reference in New Issue
Block a user