Reputation: 10191
I have a Python module that performs some logging during some of the methods it contains:
module.py
LOG_FILE = "/var/log/module.log"
def log(message):
with os.fdopen(os.open(LOG_FILE, os.O_RDWR | os.O_CREAT, 0664), "a+") as f:
f.write("[%s] %s\n" % (time.strftime("%c"), message))
def do_something():
log("Doing something")
# ...
In this implementation the log file will be opened and closed every time the log
method is called.
I'm considering refactoring it so the file is opened once when the module is loaded, but I'm not sure how to ensure it is closed when a script importing the module ends. Is there a clean way to do this?
Edit: I'm not asking about closing the file when an exception is encountered, but when the script that imports my module exits.
Upvotes: 0
Views: 1165
Reputation: 414265
OS takes care of open file descriptors then a process dies. It may lead to a data loss if file buffers inside the application are not flushed. You could add f.flush()
in the log()
function after each write (note: it does not guarantee that the data is physically written to disk and therefore it is still may be lost on a power failure, see Threadsafe and fault-tolerant file writes).
Python may also close (and flush) the file on exit during a garbage collection. But you shouldn't rely on it.
atexit
works only during a normal exit (and exit on some signals). It won't help if the script is killed abruptly.
As @René Fleschenberg suggested, use logging
module that calls .flush()
and perhaps registers atexit
handlers for you.
Upvotes: 2
Reputation: 2548
Python will automatically close the opened files for you when the script that has imported your module exits.
But really, just use Python's logging module.
Upvotes: 0
Reputation: 6566
Python is usually pretty good at cleaning up after itself. If you must do something when the script ends, you need to look at the atexit
module - but even then, it offers no guarantees.
You may also want to consider logging to either stdout
or stderr
, depending on purpose, which avoids keeping a file around all together:
import sys
def log(message):
sys.stderr.write("[%s] %s\n" % (time.strftime("%c"), message))
Upvotes: 1