32

Is there a way that I can parse a single comma delimited string without using anything fancy like a csv.reader(..) ? I can use the split(',') function but that doesn't work when a valid column value contains a comma itself. The csv library has readers for parsing CSV files which correctly handle the aforementioned special case, but I can't use those because I need to parse just a single string. However if the Python CSV allows parsing a single string itself then that's news to me.

asked Mar 6, 2016 at 3:37

4 Answers 4

51

Take a closer look at the documentation for the csv module, which says:

reader(...)
 csv_reader = reader(iterable [, dialect='excel']
 [optional keyword args])
 for row in csv_reader:
 process(row)
 The "iterable" argument can be any object that returns a line
 of input for each iteration, such as a file object or a list. The
 optional "dialect" parameter is discussed below. The function
 also accepts optional keyword arguments which override settings
 provided by the dialect.

So if you have string:

>>> s = '"this is", "a test", "of the csv", "parser"'

And you want "an object that returns a line of input for each iteration", you can just wrap your string in a list:

>>> r = csv.reader([s])
>>> list(r)
[['this is', 'a test', 'of the csv parser']]

And that's how you parse a string with the csv module.


@rafaelc suggests that iter(s) might be more elegant, but unfortunately iter(s) will return an iterator over the characters in s. That is, given:

s = "'this is', 'a test', 'of the csv parser'"
r = csv.reader(iter(s))
for row in r:
 print(row)

We would get output like:

["'"]
['t']
['h']
['i']
['s']
[' ']
['i']
['s']
["'"]
.
.
.

I don't think there's any way to create a line iterator over a single string that's going to be better than simply wrapping it in a list.

As @alexce points out in their answer, we can achieve something similar using a StringIO object, but that requires substantially more overhead. Compare the size of s wrapped in a list:

>>> sys.getsizeof([s])
64
>>> sys.getsizeof(io.StringIO(s))
184

(And there's the cost of importing the io module, which requires both memory and time).

answered Mar 6, 2016 at 3:42
Sign up to request clarification or add additional context in comments.

4 Comments

I guess it would be more elegant to use iter(s) as to a general iterator instead of [s] (specifying a list). But you have my +1
This probably won't work if the string has quoted linefeeds inside of the values; @alecxe's answer makes more sense
list(csv.reader(['"this is", "a test", "of the csv", "parser"']))[0] Boom!
@rafaelc is more elegant but will give you wrong results
24

You can still parse a single string with csv. Use StringIO to write a string buffer (also known as memory files):

import csv
from StringIO import StringIO
s = "your string"
buff = StringIO(s)
reader = csv.reader(buff)
for line in reader:
 print(line)
spedy
2,37027 silver badges26 bronze badges
answered Mar 6, 2016 at 3:41

2 Comments

For Python 3 use from io import StringIO see here
But be careful with non-ASCII strings! 'If [Unicode and 8-bit strings] are used, 8-bit strings that cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause a UnicodeError to be raised when getvalue() is called.'
15
>>> import csv
>>> s = '"Yes, this line",can be, parsed as csv'
>>> list(csv.reader([s]))[0]
['Yes, this line', 'can be', ' parsed as csv']
>>>

Basically just @larsks answer above but more brief and demonstrating that it works on csv values that have commas inside quotes.

If you upvote me, upvote the other answer too. https://stackoverflow.com/a/35822856/1196339

answered Aug 12, 2018 at 19:32

1 Comment

next(csv.reader([s])) should have even less footprint. Yes, it's minor, but since the code is also shorter, why not.
2

String to Pandas DataFrame:

import pandas as pd
from io import StringIO
csv_str="Column1,Column2\n1,2\n3,4"
buff = StringIO(csv_str)
df = pd.read_csv(buff)

DataFrame:

Out[1]: 
 Column1 Column2
 1 2
 3 4

For other delimiters add something like delimiter="\t" to read_csv().

answered Aug 29, 2021 at 10:00

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.