FAQ
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---

--
Heikki Toivonen

Search Discussions

  • Peter Otten at Mar 30, 2007 at 6:39 am

    Heikki Toivonen wrote:

    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.
    I think Exception.args always was supposed to be a tuple. Starting with 2.5
    Python enforces that constraint:

    [Python2.4]
    e = Exception()
    e.args
    ()
    e.args = "abc"
    e.args
    'abc'
    e.args = 1
    e.args
    1

    [Python 2.5]
    e = Exception()
    e.args
    ()
    e.args = "abc"
    e.args
    ('a', 'b', 'c')
    e.args = 1
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'int' object is not iterable

    The quick fix is of course
    e.args = [1]
    but also note that according to the tutorial

    http://docs.python.org/tut/node10.html#SECTION0010300000000000000000
    """
    But use of .args is discouraged. Instead, the preferred use is to pass a
    single argument to an exception (which can be a tuple if multiple arguments
    are needed) and have it bound to the message attribute.
    """

    Peter
  • Heikki Toivonen at Mar 30, 2007 at 7:36 am

    Peter Otten wrote:
    I think Exception.args always was supposed to be a tuple. Starting with 2.5
    Python enforces that constraint: [...]
    http://docs.python.org/tut/node10.html#SECTION0010300000000000000000
    """
    But use of .args is discouraged. Instead, the preferred use is to pass a
    single argument to an exception (which can be a tuple if multiple arguments
    are needed) and have it bound to the message attribute.
    """
    Excellent, thank you!

    --
    Heikki Toivonen

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedMar 30, '07 at 5:53a
activeMar 30, '07 at 7:36a
posts3
users2
websitepython.org

2 users in discussion

Heikki Toivonen: 2 posts Peter Otten: 1 post

People

Translate

site design / logo © 2022 Grokbase