2

I'm following a tutorial in a textbook, "Starting out with python 2nd edition" and I'm getting a traceback with this exercise in IDLE 3.2. I can't seem to figure out the issue, it allows me to input the number of sales then only 1 sales amount it the echos "Data written to sales.txt." then displays the prompt for day 2 but any amount entered causes a traceback:

line 118, in main sales_file.write(str(sales) + '\n') ValueError: I/O operation on closed file.

Code:

def main():

     num_days = int(input('For how many days do ' + \
                          'you have sales? '))

     sales_file = open('sales.txt', 'w')


     for count in range(1, num_days + 1):
         sales = float(input('Enter the sales for day #' + \
                             str(count) + ': '))
         sales_file.write(str(sales) + '\n')
         sales_file.close()
         print('Data written to sales.txt.')

main()
2
  • Note that you do not need ` + \ ` to do string concatenation: it is best to just remove it. In fact, consecutive string literals are automatically concatenated by Python: 'Example ' 'long string' is the same string as Example long string. Commented May 14, 2012 at 2:02
  • Also note that sales_file.write(…+'\n') is more simply written as print >> sales_file, …. Commented May 14, 2012 at 2:03

3 Answers 3

7

You are closing the file inside the for-loop. Next time through the loop when you write to the file, you are trying to write to a file that has been closed, hence the error message that says I/O operation on closed file..

Move the line

sales_file.close()

to after the print statement at the bottom of the for-loop, but indent it at the level of the for. That will close the file only once after the loop (rather than repeatedly), i.e., when you are done with it at the end of your program.

Like this:

for count in range(1, num_days + 1):
   sales = float(input('Enter the sales for day #' + str(count) + ': '))
   sales_file.write(str(sales) + '\n')
   print('Data written to sales.txt.')

sales_file.close()   # close file once when done

A better approach would be to use the with statement as it will automatically close the file for you when you are done. So you could say

with open('sales.txt', 'w') as sales_file:
   for count in range(1, num_days + 1)
      # rest of the code
      # but *no* close statement needed.
Sign up to request clarification or add additional context in comments.

1 Comment

@user1291271 Glad it worked for you! You should accept Levon's answer with the green checkmark now: it rewards both of you with reputation and marks this question as solved, so more people don't keep coming to it.
1

You could do this in a cleaner way if you used with open('sales_file','w') that way once you leave the with block it will automatically close the file. So you would edit your function to read:

def main():

    num_days = int(input('For how many days do ' + \
                        'you have sales? '))

    with open('sales.txt', 'w') as sales_file:
        for count in range(1, num_days + 1):
            sales = float(input('Enter the sales for day #' + \
                                str(count) + ': '))
            sales_file.write(str(sales) + '\n')
            print('Data written to sales.txt.')
    # once you leave the block (here) it automatically closes sales_file
main()

1 Comment

Cool, definitely look to use that in the future
0

You close the file in 1 loop and then write to it in the next iteration. Put close outside of the loop

def main():

     num_days = int(input('For how many days do ' + \
                          'you have sales? '))

     sales_file = open('sales.txt', 'w')


     for count in range(1, num_days + 1):
         sales = float(input('Enter the sales for day #' + \
                             str(count) + ': '))
         sales_file.write(str(sales) + '\n')
         print('Data written to sales.txt.')

     sales_file.close()

main()

Even better, you can use with

def main():

     num_days = int(input('For how many days do you have sales? '))

     with open('sales.txt', 'w') as sales_file:

         for count in range(1, num_days + 1):
             sales = input('Enter the sales for day #%s: ' % count)
             sales_file.write('%s\n' % sales)
             print('Data written to sales.txt.')

main()

Comments

Your Answer

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.