0

When I run this function, it hangs because I am using the open() function to read a csv and I need to close it. I put the close() function where I think it's supposed to go, however it doesn't seem to be working. I've put the close() function in line with the "while True" indent, "for i in byte" indent and it doesn't work on either. What am I doing wrong?

def parse(text): #states is_token = False previous_character_is_escape = False no_quote_value = True quote_value = False file_base = os.path.basename('"app/csv_upload_directory/%s' % text) new_base = os.path.splitext(file_base)[0] row_counter = 1 token_counter = 0 fo = open("csv_upload_directory/%s_results.csv" % new_base, "w+") fo.write("Row %i" % row_counter + '\n') row_counter += 1 with io.open(text,'rb',newline=None) as f: while True: byte = f.read(1) for i in byte: #print "%s,%s" % (no_quote_value,previous_character_is_escape) if is_token == False: if i == '"': fo.write(i) token_counter = 0 is_token = True no_quote_value = False quote_value = True elif i == '\n': fo.write(",") fo.write("%i" % token_counter) fo.write('\n') fo.write("Row %i" % (row_counter)) fo.write("\n") token_counter = 0 row_counter += 1 elif i == ',': fo.write(",") fo.write("%i" % token_counter) fo.write('\n') token_counter = 0 elif no_quote_value == True: fo.write(i) token_counter += 1 is_token = True quote_value = False else: fo.write(i) token_counter += 1 elif is_token == True: # start of an escape sequence if i == '\\': fo.write(i) token_counter += 1 previous_character_is_escape = True # for line delimiter, the quoted values are being processed outside token elif no_quote_value == True and i == '\n': fo.write(",") fo.write("%i" % token_counter) fo.write('\n') fo.write("Row %i" % (row_counter)) fo.write("\n") token_counter = 0 row_counter += 1 is_token = False # if token is not a quoted value but ends with quotes, and there is no escape character elif no_quote_value == True and previous_character_is_escape == False and i == '"': fo.write(i) fo.write("This is a not a valid token, this is not a quoted value but there is an ending quote") return False # builds off previous_character_is_escape and captures any escape sequence elif previous_character_is_escape == True: fo.write(i) token_counter += 1 previous_character_is_escape = False # this type of quote is the end of token, returns back to other if statement elif previous_character_is_escape == False and i == '"': fo.write(i) no_quote_value = True quote_value = False is_token = False # if token starts as a quote but ends without quotes elif quote_value == True and previous_character_is_escape == False and i == ',': fo.write(i) fo.write("This is not a valid token, there should be a quote at the end of this token") return False # this comma marks the end of a non quoted token, this invokes a newline elif no_quote_value == True and previous_character_is_escape == False and i == ',': fo.write(",") fo.write("%i" % token_counter) fo.write('\n') token_counter = 0 is_token = False elif no_quote_value == False and i == ',': fo.write(i) fo.write("DONG") else: fo.write(i) token_counter += 1 fo.close() parse('example.csv') 
3
  • Wrap the relevant pieces of code in try..except blocks (docs.python.org/2/tutorial/errors.html) so that you catch an Exception. The type of Exception will generally give you clues as to what is wrong. Commented Mar 28, 2016 at 5:12
  • @AlexReynolds: the parse function is working as intended, currently it gets to the end of the csv and just waits there unless I manually escape it on the console. Commented Mar 28, 2016 at 5:15
  • You don't need f.close() because your with statement takes care of it (when the with ends, the fill will be closed automatically). You probably should include fo in the same with statement (or a nested one). Other than that, the only issue I see is that your code runs forever if there's no error. You probably need to add some logic that breaks out of your while True loop when you've read all the characters. Commented Mar 28, 2016 at 5:16

2 Answers 2

1

From your comment, it sounds like closing the files is not actually your issue (though it is something you should take care of). The real issue is that your function never ends.

This is because you're looping forever, attempting to read one character per iteration. When the file has all been read, you're not noticing it that you get empty bytestrings from f.read(1). You should add some logic to break out of the loop when that happens.

A further issue: you're currently using a for loop to iterate over the one-byte string you're getting from read(1). There's no need for that loop, and it makes it hard to break out of the while loop using a break statement.

Try:

with io.open(text,'rb',newline=None) as f, fo: # add fo to the with statement while True: i = f.read(1) # read directly to "i", no need for the extra loop on bytes if i == '': # check if read gave us an empty string (happens at EOF) break if is_token == True: # ... 
Sign up to request clarification or add additional context in comments.

Comments

0

So, you are opening two files here. One with the reference of fo and the other with f.

For fo, you are using open() method to perform file operations and you need to close it appropriately with fo.close().

However, this is not the case with f. Since you are using with... open() method, you don't need to close it as it efficiently handles closing the file after its completes code block execution. Read about the related documentation here.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.