I am developing a long-running python script which makes many connections to different serial ports. The script crashes a few hours into its execution citing "Too many open files".
I have tracked the issue to the serial module where the .close() method does not seem to reduce the number of file descriptors python is using. I am checking this using lsof | grep python | wc
. Using Debian 7.2 & Python 2.7.3
The example below slowly uses up more and more file descriptors until it hits the limit. Why is this and how can I avoid it??
#!/usr/bin/env python
import serial #Used to communicate with pressure controller
import logging
import time
from time import gmtime, strftime
logging.basicConfig(filename="open_files_test.log")
# Write unusual + significant events to logfile + stdout
def log( message ):
time = strftime("%Y-%m-%d %H:%M:%S", gmtime())
logging.warning( time + " " + message )
print( message )
for i in range(2000):
for n in range(1, 12):
try:
port_name = "/dev/tty" + str(n+20)
com = serial.Serial(port_name,9600,serial.EIGHTBITS,serial.PARITY_NONE,serial.STOPBITS_ONE,0.0,False,False,5.0,False,None)
com.open()
com.flushInput()
com.flushOutput()
log("Opened port: " + port_name)
except serial.SerialException:
com = None
log("could not open serial port: " + port_name)
com.close()
log("Closed port: " + port_name)
time.sleep(1)
log("Finished Program")
Thanks
As long as your program is running, if you keep opening files without closing them, the most likely result is that you will run out of file descriptors/handles available for your process, and attempting to open more files will fail eventually.
Not closing a file after an interaction is not only a waste of program resources but could also prevent other file interactions and may lead to inconsistencies when running your scripts on different Python versions.
close() closes a file descriptor, so that it no longer refers to any file and may be reused.
Yes, close your file descriptors and free all heap memory, even if you know that the OS will clean it up - that way, when you run valgrind or some similar tool, you don't get a lot of noise in the results, and you can easily recognize "legit" fd leaks.
It seems that extra com.open
is causing the issue. According to the docs serial.Serial
returns it open, so you don't need to open it once more. In Linux (all POSIXes as far as I know) open
just increments the counter and close just decrements it. There is a deleted answer here by @wheaties advising using with
which I would recommend as well:
with serial.Serial(port_name, 9600, ...) as com:
com.flushInput()
com.flushOutput()
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With