Prev: The inverse of .join
Next: how to get bit info
From: Stephen Hansen on 17 Jun 2010 18:16 On 6/17/10 3:06 PM, Laurent Verweijen wrote: >> >> In your other thread you include an actual traceback: >> >> Traceback (most recent call last): >> File "subchronous_test.py", line 5, in <module> >> send_all(str(p), n) >> File "/home/Somelauw/asynchronous.py", line 145, in send_all >> while len(data): >> TypeError: object of type 'int' has no len() >> >> The first argumetn to send_all should be the actual Popen subclass. The >> second should be a string to send. I think that line really is intended >> to be: >> >> send_all(p, str(n)) # assuming 'n' is say, the number 5. >> > > You are right, I swapped the parameters, but even if I correct it, it > still gives the second error. > General rule of thumb: its best to never use the word "still" when it comes to debugging Python and exceptions, unless you are absolutely certain the exception is precisely the same. I don't doubt that you may still get an exception on send_all; but there is no way you're getting the *same* exception (that specific type error: attempting to call len() on an integer) if you corrected your arguments. You're getting the EOFError, because you're never sending anything to the subprocess. You're not getting anything from the subprocess because it never receives anything to send back. And apparently there's an error on send, which is causing that problem, but that error is...? -- Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/
From: Laurent Verweijen on 18 Jun 2010 11:47
Op donderdag 17-06-2010 om 15:16 uur [tijdzone -0700], schreef Stephen Hansen: > On 6/17/10 3:06 PM, Laurent Verweijen wrote: > >> > >> In your other thread you include an actual traceback: > >> > >> Traceback (most recent call last): > >> File "subchronous_test.py", line 5, in <module> > >> send_all(str(p), n) > >> File "/home/Somelauw/asynchronous.py", line 145, in send_all > >> while len(data): > >> TypeError: object of type 'int' has no len() > >> > >> The first argumetn to send_all should be the actual Popen subclass. The > >> second should be a string to send. I think that line really is intended > >> to be: > >> > >> send_all(p, str(n)) # assuming 'n' is say, the number 5. > >> > > > > You are right, I swapped the parameters, but even if I correct it, it > > still gives the second error. > > > > General rule of thumb: its best to never use the word "still" when it > comes to debugging Python and exceptions, unless you are absolutely > certain the exception is precisely the same. > > I don't doubt that you may still get an exception on send_all; but there > is no way you're getting the *same* exception (that specific type error: > attempting to call len() on an integer) if you corrected your arguments. > > You're getting the EOFError, because you're never sending anything to > the subprocess. You're not getting anything from the subprocess because > it never receives anything to send back. And apparently there's an error > on send, which is causing that problem, but that error is...? > My last post, contains the output after I fixed swapping the parameters and everything you said. I think there is still a problem with output that gets blocked. Couldn't it be just that the output which gets blocked is causing this error? Anyway here is the output again: python subchronous_test.py Traceback (most recent call last): File "increment.py", line 8, in <module> n = int(raw_input(str(n))) + 1 EOFError: EOF when reading a line close failed in file object destructor: Error in sys.excepthook: Original exception was: And here are all 3 files concatenated: # subchronous_test import sys from asynchronous import * p = Popen(["python", "increment.py"], stdin=PIPE, stdout=PIPE, stderr = sys.stderr) for n in [5, 7, 10, 4]: send_all(p, str(n)) print(recv_some(p)) # increment.py import sys, traceback try: n = 0 while True: n = int(raw_input(str(n))) + 1 except: print >>sys.stderr, traceback.format_exc() # asynchronous.py ## {{{ http://code.activestate.com/recipes/440554/ (r10) 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() ## end of http://code.activestate.com/recipes/440554/ }}} |