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(['Статус', 'Количество'])
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(['Статус', 'Количество'])
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(['Статус', 'Количество'])
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(...)
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(['Статус', 'Количество'])
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.
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.
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(['Статус', 'Количество'])
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(['Статус', 'Количество'])
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(['Статус', 'Количество'])
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(...)
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(['Статус', 'Количество'])
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.
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.