flybonzai
flybonzai

Reputation: 3931

CSV Reader object getting ValueError: I/O operation on closed file?

I'm creating a csv.reader object, setting it as an instance variable, but then when I try to iterate through it I get an error saying I'm trying to operate on a closed file. Is the reader still linked to the file somehow? I'm assigning it within my with open(blah) block, so I'm confused as to why this is happening.

Here is my code:

    def __init__(self, infile, header_file, transact_file):
        self.infile = infile
        self.header_of = header_file
        self.transact_of = transact_file

    def create_reader(self):
        """Create a csv reader."""

        with open(self.infile, 'r') as inf:
            logging.info('Infile name: {0}'.format(inf))
            self.csv_reader = reader(inf, quotechar='"')

    def parse_headers(self):
        """Separate header files ("H", "S") from transaction files."""

        headers = []
        transactions = []

        for row in self.csv_reader:
            row_type = row[0]
            logging.info('Row type is: {0}'.format(row_type))
            if row_type == 'H':
                logging.info('Row added to header list.')
                headers.append(row)
            elif row_type == 'S':
                if row not in headers:
                    logging.info('Row added to header list.')
                    headers.append(row)
            else:
                logging.info('Row added to transaction list.')
                transactions.append(row)

        # Debugging and verification
        logging.info('Header list contains: {0}'.format('\n'.join([str(header) for header
            in headers])))
        logging.info('Transaction list contains: {0}'.format(
            '\n'.join([str(trans) for trans in transactions])))

Here is my error stack:

Traceback (most recent call last):                                                                                    x
  File "./gen_pre.py", line 155, in <module>                                                                          x
    main()                                                                                                            x
  File "./gen_pre.py", line 25, in main                                                                               x
    parser.run_process()                                                                                              x
  File "./gen_pre.py", line 140, in run_process                                                                       x
    self.parse_headers()                                                                                              x
  File "./gen_pre.py", line 68, in parse_headers                                                                      x
    for row in self.csv_reader:                                                                                       x
ValueError: I/O operation on closed file  

Upvotes: 2

Views: 1628

Answers (2)

Trey Hunner
Trey Hunner

Reputation: 11804

Context managers are great because they automatically close files for you. Instead of manually opening and closing the file, you could read the whole file and pass a list of the rows to the CSV reader:

def create_reader(self):
    """Create a csv reader."""
    with open(self.infile, 'r') as inf:
        logging.info('Infile name: {0}'.format(inf))
        file_data = inf.readlines()
    self.csv_reader = reader(file_data, quotechar='"')

The csv.reader object will accept anything it can iterate over, so a list of each line in the file (from readlines) will work fine.

Upvotes: 2

furas
furas

Reputation: 142631

with automatically closes the file when you leave the block.

You have to do

self.inf = open(self.infile, 'r')

self.csv_reader = reader(self.inf, quotechar='"') # self.inf

and you will have to close the file manually.

def close_reader(self):
    self.csv_reader.close()
    self.inf.close()

Upvotes: 3

Related Questions