Reputation: 63
I am handling a csv import and got troubles with a value that should be in list form but is read as string.
One of the csv rows looks like the following:
['name1', "['name2', 'name3']"]
As you can see the value in the second column is a list but is read as a string. My problem is that I need to iterate through that list and the length of that list can vary from row to row.
I am wondering where the problem lies. Can csv read not handle a list? Is there a way to turn that string in the second column into a list rather than using regex? Here is the code that I am running:
import csv
import os
content = []
file_path = os.path.abspath(file)
if os.path.exists(file_path):
with open(file_path, 'rb') as csvfile:
csvreader = csv.reader(csvfile, delimiter = ',')
for row in csvreader:
content.append(row)
for row in content[1:5]:
print row
print row[0], row[1]
for name in row[1]:
print name
The output row looks as above but when iterating though row[1] it does not iterate though the list of names but through every single character. Anyone got an idea? Thanks in advance for any help!
Upvotes: 0
Views: 112
Reputation: 90899
An easy way to convert string to list is using ast.literal_eval
function.
Example -
>>> import ast
>>> s = "['name2', 'name3']"
>>> s
"['name2', 'name3']"
>>> l = ast.literal_eval(s)
>>> l
['name2', 'name3']
>>> type(l)
<class 'list'>
From ast documentation -
ast.literal_eval(node_or_string)
Safely evaluate an expression node or a Unicode or Latin-1 encoded string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.
But if your complete csv looks like that, you should consider using json
to parse the csv, rather than csv
module.
Upvotes: 3
Reputation: 67968
x=['name1', "['name2', 'name3']"]
import re
print [ast.literal_eval(i) if re.match(r"\[.*?\]",i) else i for i in x ]
OUTPUT: ['name1', ['name2', 'name3']]
You can use ast.literal_eval
and re
to convert string in list to list and leave others as they are.
Upvotes: 0
Reputation: 20349
Try this, using literal_eval
to convert string to corresponding class
from ast import literal_eval
for name in literal_eval(row[1]):
print name
or
for name in eval(row[1]):
print name
Upvotes: 1
Reputation: 63737
Considering your second list item is a valid python data type, you can use ast.literal_eval
to parse the string
>>> import ast
>>> ast.literal_eval("['name2', 'name3']")
['name2', 'name3']
So in your particular case,you may want to do the following
.............
row[1] = ast.literal_eval(row[1])
print row[0], row[1]
for name in row[1]:
print name
Upvotes: 1