Reading csv file

Igor Korot ikorot01 at gmail.com
Thu Dec 19 04:22:26 EST 2013


Hi, Peter,
Thank you for the great suggestion.

I tried to implement you code but failed.

Here's what I have:

class FileReader:
        def __init__(self, filename, isSkip):
                self.path = filename
                self.isSkip = isSkip

        @contextmanager
        def open(*args):
                from StringIO import StringIO
                lines = range(10)
                if self.isSkip:
                        lines[0] = "skipped"
                        lines[6] = "field1-from-line6,field2-from-line6"
                else:
                        lines[0] = "field1-from-line1,field2-from-line1"
                yield StringIO("\r\n".join(map(str, lines)))

        def is_arbitrary_text(self,fieldnames):
                return "skipped" in fieldnames

        def readData(self):
                with self.open(self.path, "r") as f:
                        reader = csv.DictReader(f)
                        if self.is_arbitrary_text(reader.fieldnames):
                                for _ in range(5):
                                        next(reader, None)
                                reader._fieldnames = None
                        for row in reader:
                                print row

Unfortunately this does not work as "def open()" does not belong to my
class and if I comment the "@contextmanager" line
I will get an exception: "AttributeError: __exit__"

Any idea what to do?

Thank you.


On Tue, Dec 17, 2013 at 2:51 AM, Peter Otten <__peter__ at web.de> wrote:
> Igor Korot wrote:
>
>> Hi, guys,
>>
>> On Tue, Dec 17, 2013 at 12:55 AM, Peter Otten <__peter__ at web.de> wrote:
>>> Peter Otten wrote:
>>>
>>>> You are still reading the complete csv file. Assuming
>>>>
>>>> (1) the first row of the csv contains the column names
>>>> (2) you want to skip the first five rows of data
>>
>> Looking at the Peter's reply I realized I missed very important piece:
>>
>> The first row may or may not contain column names.
>> If it does not, the first row will just contain some text, i.e. "abc"
>> and the column names will be located on the row 6.
>>
>> I know if does complicate things but I am deeply sorry.
>> The csv file is generated by some program run and I guess depending on
>> the switches passed to
>> that program it either creates the header in the csv (report name,
>> time slice it ran at, user it ran under
>> and some other info.
>> Or it can be run without such switch and then it generates a normal csv.
>>
>> The report it generates is huge: it has about 30+ fields and I need to
>> read this report, parse it and
>> push accordingly to the database of mySQL.
>>
>> Thank you for any suggestions and sorry for not posting complete task.
>
> Try the following (without the mock-ups of course):
>
>
> $ cat csv_skip_header.py
> import csv
> import sys
> from contextlib import contextmanager
>
> filename = "ignored"
>
> @contextmanager
> def open(*args):
>     "mock-up, replace with open() built-in"
>     from StringIO import StringIO
>     lines = range(10)
>     if len(sys.argv) > 1 and sys.argv[1] == "--skip":
>         lines[0] = "skipped"
>         lines[6] = "field1-from-line6,field2-from-line6"
>     else:
>         lines[0] = "field1-from-line1,field2-from-line1"
>     yield StringIO("\r\n".join(map(str, lines)))
>
> def is_arbitrary_text(fieldnames):
>     "mock-up, replace with the actual check"
>     return "skipped" in fieldnames
>
> with open(filename, "rb") as f:
>     reader = csv.DictReader(f)
>     if is_arbitrary_text(reader.fieldnames):
>         for _ in range(5):
>             next(reader, None)
>         reader._fieldnames = None # underscore necessary,
>                                   # fieldnames setter doesn't work
>         reader.fieldnames # used for its side-effect
>     for row in reader:
>         print row
> $ python csv_skip_header.py
> {'field2-from-line1': None, 'field1-from-line1': '1'}
> {'field2-from-line1': None, 'field1-from-line1': '2'}
> {'field2-from-line1': None, 'field1-from-line1': '3'}
> {'field2-from-line1': None, 'field1-from-line1': '4'}
> {'field2-from-line1': None, 'field1-from-line1': '5'}
> {'field2-from-line1': None, 'field1-from-line1': '6'}
> {'field2-from-line1': None, 'field1-from-line1': '7'}
> {'field2-from-line1': None, 'field1-from-line1': '8'}
> {'field2-from-line1': None, 'field1-from-line1': '9'}
> $ python csv_skip_header.py --skip
> {'field1-from-line6': '7', 'field2-from-line6': None}
> {'field1-from-line6': '8', 'field2-from-line6': None}
> {'field1-from-line6': '9', 'field2-from-line6': None}
>
> You may find the following a bit cleaner:
>
> with open(filename, "rb") as f:
>     reader = csv.reader(f)
>     fieldnames = next(reader)
>     if is_arbitrary_text(fieldnames):
>         for _ in range(5):
>             next(reader, None)
>         fieldnames = None
>     reader = csv.DictReader(f, fieldnames=fieldnames)
>     for row in reader:
>         print row
>
> Or you do the skipping on the file (only if the rows don't have embedded
> newlines).
>
> --
> https://mail.python.org/mailman/listinfo/python-list



More information about the Python-list mailing list