Python未关闭文件描述符

8

我正在开发一个长时间运行的Python脚本,它会连接到许多不同的串口。脚本在执行几个小时后崩溃,提示“打开文件太多”。

我已经追踪了这个问题,发现是由于串口模块中的.close()方法似乎没有减少Python正在使用的文件描述符数目。我使用lsof | grep python | wc来检查这一点。我使用的操作系统是Debian 7.2和Python 2.7.3。

下面的示例会逐渐使用更多的文件描述符,直到达到限制。为什么会出现这种情况,我应该如何避免它?

#!/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")

谢谢


在文件处理完成后调用GC。 - BinaryThor
@BinaryThor:他这样做。在try..except语句之后,有com.close() - jazzpi
@Shiftee,你遇到任何被记录的错误吗? - glglgl
@glglgl 不是的。我的主程序引发了一个IOError错误,但我在日志文件中找不到任何有用信息。 - Shiftee
2个回答

5
看起来多余的com.open导致了问题。根据文档serial.Serial返回它打开,因此您不需要再次打开它。在Linux(据我所知,所有POSIX)中,open只增加计数器,并且close只减少计数器。这里删除了@wheaties的答案,建议使用with,我也推荐使用它:
with serial.Serial(port_name, 9600, ...) as com:
    com.flushInput()
    com.flushOutput()
    ...

2

使用finally确保端口关闭。

try:
    ...
except serial.SerialException:
    ...
finally:
    com.close()

com.close 的调用是在 try..except 之后进行的,因此它无论如何都会被执行。 - jazzpi
@jazzpi 除了 SerialException 之外的异常都不行... 而且,在 com = None 之后,它仍然会失败。 - glglgl
@tim 一般来说,这是一个很好的风格,但在这里可能没有帮助,因为 close() 无论如何都会被调用。 - glglgl
@glglgl:是的,但这会导致另一个错误而不是“打开太多文件”。 - jazzpi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接