how to iterate over sequence and non-sequence ?

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Fri Oct 19 04:58:36 EDT 2007


On Fri, 19 Oct 2007 01:24:09 +0200, stef mientki wrote:

> hello,
> 
> I generate dynamically a sequence of values, but this "sequence" could
> also have length 1 or even length 0.
> 
> So I get some line in the form of:
>       line = '(2,3,4)'
>       line = ''
>       line = '(2)'
> (in fact these are not constant numbers, but all kind of integer
> variables, coming from all over the program, selected from a tree, that
> shows all "reachable" variables)
> 
> So in fact I get the value from an exec statement, like this
>       exec 'signals = ' + line

And then, one day, somebody who doesn't like you will add the following 
to your input data:

"0; import os; os.system('rm # -rf /')"

[ Kids: don't try this at home! Seriously, running that command will be 
bad for your computer's health. Or at least it would, if I hadn't put a 
spike in it. ]

Don't use exec in production code unless you know what you're doing. In 
fact, don't use exec in production code.


> Now I want to iterate over "signals", which works perfect if there are 2
> or more signals,
> but it fails when I have none or just 1 signal.
>     for value in signals :
>         do something


No, I would say it already failed before it even got there.

>>> line = ''
>>> exec 'signals = ' + line
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<string>", line 1
    signals =
            ^
SyntaxError: unexpected EOF while parsing



This is the right way to deal with your data:

input_data = """  (2, 3  , 4) 

  (2)
(3,4,5)
( 1, 2,3)
"""

for line in input_data.split('\n'):
    line = line.strip().strip('()')
    values = line.split(',')
    for value in values:
        value = value.strip()
        if value:
            print(value)


> As this meant for real-time signals, I want it fast, so (I think) I
> can't afford extensive testing.

Don't guess, test it and see if it is fast enough. Some speed ups:

If you're reading from a file, you can just say: "for line in file:" 
instead of slurping the whole lot into one enormous string, then 
splitting over newlines.

If you can guarantee that there is no extra whitespace in the file, you 
can change the line 

    line = line.strip().strip('()')

to the following:

    line = line.strip('\n()')

and save a smidgen of time per loop. Likewise, drop the "value = 
value.strip()" in the inner loop.


-- 
Steven.



More information about the Python-list mailing list