H
Heikki Toivonen
We have successfully used a script to run external programs for several
years. Now we upgraded our Python to 2.5, and are hitting a mysterious
error.
The expected output from the sample script (see below) with 2.4 looks
like this:
ret ['5\n']
else
********************
ExternalCommandErrorWithOutputList 1 ['Traceback (most recent call
last):\n', ' File "<string>", line 1, in ?\n', 'ZeroDivisionError:
integer division or modulo by zero\n']
********************
ret ['6\n', '7\n', '8\n']
else
********************
With 2.5 we get:
ret ['5\n']
else
********************
Exception 'int' object is not iterable
Traceback (most recent call last):
File "...test.py", line 43, in <module>
ret = executeCommandReturnOutput(cmd)
File "...test.py", line 6, in __init__
self.args = args[0]
TypeError: 'int' object is not iterable
********************
ret ['6\n', '7\n', '8\n']
else
********************
What is going on? How do we fix this? We'd like to be able to run with
both python 2.4 and 2.5.
And here is the script:
---CLIP---
import os, traceback, sys
class ExternalCommandErrorWithOutputList(Exception):
def __init__(self,args=None):
if args:
self.args = args[0]
self.outputList = args[1]
else:
self.args = args
self.outputList = []
def executeCommandReturnOutput(args):
args_str = ' '.join(args)
if os.name not in ['nt', 'os2']:
import popen2
p = popen2.Popen4(args_str)
p.tochild.close()
outputList = p.fromchild.readlines()
exitCode = p.wait()
if exitCode == 0:
exitCode = None
else:
exitCode >>= 8
else:
i,k = os.popen4(args_str)
i.close()
outputList = k.readlines()
exitCode = k.close()
if exitCode is not None:
raise ExternalCommandErrorWithOutputList, [exitCode, outputList]
return outputList
if __name__ == "__main__":
for cmd in [['python', '-c', '"print 5"'],
['python', '-c', '"1/0"'],
['python', '-c', '"print 6;import
sys;sys.stdout.flush();print >>sys.stderr, 7;print 8"'],
]:
try:
ret = executeCommandReturnOutput(cmd)
print 'ret', ret
except ExternalCommandErrorWithOutputList, e:
print 'ExternalCommandErrorWithOutputList', e, e.outputList
except Exception, e:
print 'Exception', e
type, value, stack = sys.exc_info()
print ''.join(traceback.format_exception(type, value, stack))
except:
print 'except'
type, value, stack = sys.exc_info()
print ''.join(traceback.format_exception(type, value, stack))
else:
print 'else'
print '*' * 20
---CLIP---
years. Now we upgraded our Python to 2.5, and are hitting a mysterious
error.
The expected output from the sample script (see below) with 2.4 looks
like this:
ret ['5\n']
else
********************
ExternalCommandErrorWithOutputList 1 ['Traceback (most recent call
last):\n', ' File "<string>", line 1, in ?\n', 'ZeroDivisionError:
integer division or modulo by zero\n']
********************
ret ['6\n', '7\n', '8\n']
else
********************
With 2.5 we get:
ret ['5\n']
else
********************
Exception 'int' object is not iterable
Traceback (most recent call last):
File "...test.py", line 43, in <module>
ret = executeCommandReturnOutput(cmd)
File "...test.py", line 6, in __init__
self.args = args[0]
TypeError: 'int' object is not iterable
********************
ret ['6\n', '7\n', '8\n']
else
********************
What is going on? How do we fix this? We'd like to be able to run with
both python 2.4 and 2.5.
And here is the script:
---CLIP---
import os, traceback, sys
class ExternalCommandErrorWithOutputList(Exception):
def __init__(self,args=None):
if args:
self.args = args[0]
self.outputList = args[1]
else:
self.args = args
self.outputList = []
def executeCommandReturnOutput(args):
args_str = ' '.join(args)
if os.name not in ['nt', 'os2']:
import popen2
p = popen2.Popen4(args_str)
p.tochild.close()
outputList = p.fromchild.readlines()
exitCode = p.wait()
if exitCode == 0:
exitCode = None
else:
exitCode >>= 8
else:
i,k = os.popen4(args_str)
i.close()
outputList = k.readlines()
exitCode = k.close()
if exitCode is not None:
raise ExternalCommandErrorWithOutputList, [exitCode, outputList]
return outputList
if __name__ == "__main__":
for cmd in [['python', '-c', '"print 5"'],
['python', '-c', '"1/0"'],
['python', '-c', '"print 6;import
sys;sys.stdout.flush();print >>sys.stderr, 7;print 8"'],
]:
try:
ret = executeCommandReturnOutput(cmd)
print 'ret', ret
except ExternalCommandErrorWithOutputList, e:
print 'ExternalCommandErrorWithOutputList', e, e.outputList
except Exception, e:
print 'Exception', e
type, value, stack = sys.exc_info()
print ''.join(traceback.format_exception(type, value, stack))
except:
print 'except'
type, value, stack = sys.exc_info()
print ''.join(traceback.format_exception(type, value, stack))
else:
print 'else'
print '*' * 20
---CLIP---