Python closing file

Question:

I need to close file, but I can’t do that, because I use csv.writer, how can I close file? python

def open_spider(self, spider):
    time = dt.now().strftime(TIME_FORMAT)
    file_path = self.results_dir / FILE_NAME.format(time)
    self.file = csv.writer(open(file_path, 'w'))
    self.file.writerow(['Статус', 'Количество'])
Asked By: xvovanbart

||

Answers:

Simply define the open() first

f = open(file_path, 'w')
self.file = csv.writer(f)
self.file.writerow(['Статус', 'Количество'])
f.close()

Or use context manager via with. You don’t need to manually close in this case

with open(file_path, 'w') as f:
    self.file = csv.writer(f)
    self.file.writerow(['Статус', 'Количество'])
Answered By: NoThlnG

Instead of manually closing the file, it is a good practice to wrap the function under with.

def open_spider(self, spider):
    time = dt.now().strftime(TIME_FORMAT)
    file_path = self.results_dir / FILE_NAME.format(time)
    with open(file_path, 'w') as file:
        self.file = csv.writer(file)
        self.file.writerow(['Статус', 'Количество'])
Answered By: Aniket Ray

You need to refactor your code so that the code captures the file handle; then you can easily call .close() on it when you are done.

But a better solution still is to use with open, which is also robust against exceptions. The file will be closed even if the code inside the with block raises an exception which is caught somewhere in the code which calls your function.

def open_spider(self, spider):
    time = dt.now().strftime(TIME_FORMAT)
    file_path = self.results_dir / FILE_NAME.format(time)
    with open(file_path, 'w')  as handle:
        self.file = csv.writer(handle)
        self.file.writerow(['Статус', 'Количество'])

However, perhaps you want to just open at this time, and save self.handle so that you can close it later – the name and design of your function suggests that you want to continue writing data to self.file, and only then self.handle.close()

Ideally, perhaps you would like to make a spider_writer object which is also a context manager, so that you can say

with spider_writer(filename) as writer:
     writer.write(...)
Answered By: tripleee

The best way to close a file is by using the with statement. This ensures that the file is closed when the block inside the with statement is exited so you do not need to explicitly call the close() method and it is internally done.
For example:

with open(file_path, 'w') as ff:
    self.file = csv.writer(ff)
    self.file.writerow(['Статус', 'Количество'])
Answered By: raiyan22

You can use the "with" keyword which htakes care of closing the file. With a little rewrite you get:

import csv

class A():
    def __init__(self):
        pass
    
    def open_spider(self, spider):
        time = "12_00_00"
        file_path= f"test_{time}.csv"
    
        #file_path = self.results_dir / FILE_NAME.format(time)
    
        with open(file_path, 'w') as csv_file:
            self.file = csv.writer(csv_file)
            self.file.writerow(['Статус'.encode("utf-8"), 'Количество'.encode("utf-8")])
        
a=A()
spider = 'fasdfsafd'
a.open_spider(spider)

Furthermore I had to encode the strings you provided as they are not ascii. Using the clock time is something for you to fix.

Answered By: Ronald van Elburg

You can just do f = open(file_path, 'w') and then csv.writer(f). Here is the code:

def open_spider(self, spider):
    time = dt.now().strftime(TIME_FORMAT)
    file_path = self.results_dir / FILE_NAME.format(time)
    f = open(file_path, 'w')
    self.file = csv.writer(f)
    self.file.writerow(['Статус', 'Количество'])
    f.close()

Or you can use self.f instead of f to close the file later.

However there is another way. It is to use with construction. Here is how it works:

with open(file_path, 'w') as f:
    # do something with the file f here
# here the file should be closed automatically

The reason why it works is that python calls __enter__ method of f upon entering with construction (which does nothing) and then it calls __exit__ method of f upon exiting with construction (which closes the file). Here is the code:

def open_spider(self, spider):
    time = dt.now().strftime(TIME_FORMAT)
    file_path = self.results_dir / FILE_NAME.format(time)
    with open(file_path, 'w') as f:
        self.file = csv.writer(f)
        self.file.writerow(['Статус', 'Количество'])

The reason why you should use with is that it’s exception-proof. That means that if an exception appears within with construction, it will close the file and raise the exception only after that. So the file will be closed even if something goes wrong while writing to that file.

Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.