tags:

views:

222

answers:

6

Hi,

I have the following problem:

  # line is a line from a file that contains ["baa","beee","0"]
  line = TcsLine.split(",")
  NumPFCs = eval(line[2])
  if NumPFCs==0:
     print line

I want to print all the lines from the file if the second position of the list has a value == 0.

I print the lines but after that the following happens: Traceback (most recent call last):

['baaa', 'beee', '0', '\n']

BUT after I have the next ERROR

ilation.py", line 141, in ?
    getZeroPFcs()
ilation.py", line 110, in getZeroPFcs
    NumPFCs = eval(line[2])
  File "<string>", line 0

Can you please help me? thanks

What0s

A: 

Your question is kind of hard to read, but using eval there is definitely not a good idea. Either just do a direct string comparison:

line=TcsLine.split(",")
if line[2] == "0":
    print line

or use int

line=TcsLine.split(",")
if int(line[2]) == 0:
    print line

Either way, your bad data will fail you.

I'd also recomment reading PEP 8.

Dustin
Does a string containing '"0"]' convert reliably?
Jonathan Leffler
A: 

There are a few issues I see in your code segment:

  1. you make an assumption that list always has at least 3 elements
  2. eval will raise exception if containing string isn't valid python
  3. you say you want second element, but you access the 3rd element.

This is a safer way to do this

line=TcsLine.split(",")
if len(line) >=3 and line[2].rfind("0") != -1:
     print line
Kozyarchuk
Does that mean that if the third value is "101" it will be printed?
Jonathan Leffler
i agree this is better with line[2] == "0" instead of a rfind
Andrew Cox
A: 

I'd recommend using a regular expression to capture all of the variants of how 0 can be specified: with double-quotes, without any quotes, with single quotes, with extra whitespace outside the quotes, with whitespace inside the quotes, how you want the square brackets handled, etc.

Mr Fooz
+1  A: 

Let me explain a little what you do here.

If you write:

NumPFCs = eval(line[2])

the order of evaluation is:

  • take the second character of the string line, i.e. a quote '"'
  • eval this quote as a python expression, which is an error.

If you write it instead as:

NumPFCs = eval(line)[2]

then the order of evaluation is:

  • eval the line, producing a python list
  • take the second element of that list, which is a one-character string: "0"
  • a string cannot be compared with a number; this is an error too.

In your terms, you want to do the following:

NumPFCs = eval(eval(line)[2])

or, slightly better, compare NumPFCs to a string:

if NumPFCs == "0":

but the ways this could go wrong are almost innumerable. You should forget about eval and try to use other methods: string splitting, regular expressions etc. Others have already provided some suggestions, and I'm sure more will follow.

ΤΖΩΤΖΙΟΥ
A: 

There are many ways of skinning a cat, as it were :)

Before we begin though, don't use eval on strings that are not yours so if the string has ever left your program; i.e. it has stayed in a file, sent over a network, someone can send in something nasty. And if someone can, you can be sure someone will.

And you might want to look over your data format. Putting strings like ["baa","beee","0", "\n"] in a file does not make much sense to me.

The first and simplest way would be to just strip away the stuff you don't need and to a string comparison. This would work as long as the '0'-string always looks the same and you're not really after the integer value 0, only the character pattern:

TcsLine = '["baa","beee","0"]'

line = TcsLine.strip('[]').split(",")
if line[2] == '"0"':
   print line


The second way would be to similar to the first except that we cast the numeric string to an integer, yielding the integer value you were looking for (but printing 'line' without all the quotation marks):

TcsLine = '["baa","beee","0"]'

line = [e.strip('"') for e in TcsLine.strip('[]').split(",")]
NumPFCs = int(line[2])
if NumPFCs==0:
   print line


Could it be that the string is actually a json array? Then I would probably go get simplejson to parse it properly if I were running Python<2.6 or just import json on Python>=2.6. Then cast the resulting '0'-string to an integer as in the previous example.

TcsLine = '["baa","beee","0"]'

#import json # for >= Python2.6
import simplejson as json # for <Python2.6

line = json.loads(TcsLine)
NumPFCs = int(line[2])
if NumPFCs==0:
   print line
Henrik Gustafsson
A: 

thanks a lot for your help guys.

Actually the: if NumPFCs == "0":

solve the problem. But I think I can do that even better using regulas expressions...

But... I don't understand much about regulas expressions. Can you please tell me where can I read something really good to learn Regular Expressions?

Thanks