Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python csv writer "AttributeError: __exit__" issue

Tags:

csv

python-2.7

I have three variables I want to write in a tab delimited .csv, appending values each time the script iterates over a key value from the dictionary.

Currently the script calls a command, regex the stdout as out then assigns the three defined regex groups to individual variables for writing to .csv labeled first second and third. I get a __exit_ error when I run the below script.

/note I've read up on csv.writer and I'm still confused as to whether I can actually write multiple variables to a row.

Thanks for any help you can provide.

 import csv, re, subprocess

 for k in myDict:
     run_command = "".join(["./aCommand", " -r data -p ", str(k)])
     process = subprocess.Popen(run_command,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
     out, err = process.communicate()
     errcode = process.returncode
     pattern = re.compile('lastwrite|(\d{2}:\d{2}:\d{2})|alert|trust|Value')
     grouping = re.compile('(?P<first>.+?)(\n)(?P<second>.+?)([\n]{2})(?P<rest>.+[\n])', 
                           re.MULTILINE | re.DOTALL)


    if pattern.findall(out):         
        match = re.search(grouping, out)
        first = match.group('first')
        second = match.group('second')
        rest = match.group('rest')

     with csv.writer(open(FILE, 'a')) as f:
        writer = csv.writer(f, delimiter='\t')
        writer.writerow(first, second, rest)

Edit: Requested in the comments to post entire traceback, note the line listed in traceback will not match the above code as this is not the entire script.

Traceback (most recent call last):
File "/mydir/pyrr.py", line 60, in <module>
run_rip()
File "/mydir/pyrr.py", line 55, in run_rip
with csv.writer(open('/mydir/ntuser.csv', 'a')) as f:
AttributeError: __exit__

Answer: Using the below comment I was able to write it as follows.

f = csv.writer(open('/mydir/ntuser.csv', 'a'),
                       dialect=csv.excel,
                       delimiter='\t')
f.writerow((first, second, rest))
like image 302
ImNotLeet Avatar asked Feb 19 '16 04:02

ImNotLeet


1 Answers

The error is pretty clear. The with statement takes a context manager, i.e., an object with an __enter__ and an __exit__ method, such as the object returned by open. csv.writer does not provide such an object. You are also attempting to create the writer twice:

with open(FILE, 'a') as f:
    writer = csv.writer(f, delimiter='\t')
    writer.writerow(first, second, rest)

The with ... f: is like a try...except...finally that guarantees that f is closed no matter what happens, except you don't have to type it out. open(...) returns a context manager whose __exit__ method is called in that finally block you don't have to type. That is what your exception was complaining about. open returns an object that has __exit__ properly defined and can therefore handle normal exit and exceptions in the with block. csv.writer does not have such a method, so you can't use it in the with statement itself. You have to do it in the with block following the statement, as I've shown you.

like image 180
Mad Physicist Avatar answered Oct 01 '22 12:10

Mad Physicist