首页 > 解决方案 > Python:http.server.HTTPServer:如何关闭所有打开的文件?

问题描述

所以基本上,我在 Python 3 中制作了一个 HTTP webhooks 服务器,并想添加一个重启功能,因为 shell 访问在它将运行的服务器上非常有限。

我早些时候在 Stack Overflow 上的某个地方找到了这个片段:

def restart_program():
    """Restarts the current program, with file objects and descriptors
       cleanup
    """

    try:
        p = psutil.Process(os.getpid())
        fds = p.open_files() + p.connections()
        print (fds)
        for handler in fds:
            os.close(handler.fd)
    except Exception as e:
        logging.error(e)

    python = sys.executable
    os.execl(python, python, *sys.argv)

在大多数情况下,它可以工作,但我想确保所以我运行了一些测试,lsof发现每次我重新启动服务器时,都会在打开的文件列表中添加两行(文件):

python3 13923 darwin    5u  systm 0x18cd0c0bebdcbfd7        0t0            [ctl com.apple.netsrc id 9 unit 36]
python3 13923 darwin    6u   unix 0x18cd0c0beb8fc95f        0t0            ->0x18cd0c0beb8fbcdf

(每次重启的地址都不同)

这些仅在我启动时出现httpd = ThreadingSimpleServer((host, port), Handler)。但即使在我调用httpd.server_close()这些打开的文件后仍然存在并且 psutil 似乎没有找到它们。

这不是真正需要的功能。如果这被证明开销太大,我可以放弃它,但现在我只对为什么我的代码不起作用以及我自己的理智的解决方案感兴趣。

提前致谢!

更新

更改p.connections()p.connections(kind='all')让我unix输入 fd 类型。仍然不确定如何关闭systm类型 fd。原来unixfd与DNS有关......

更新

好吧,看起来我找到了解决方案,尽管它可能很混乱。

class MyFileHandler(object):
    """docstring for MyFileHandler."""
    def __init__(self, fd):
        super(MyFileHandler, self).__init__()
        self.fd = fd

def get_open_systm_files(pid=os.getpid()):
    proc = subprocess.Popen(['lsof', '-p', str(pid)], stdout=subprocess.PIPE)
    return [MyFileHandler(int(str(l).split(' ')[6][:-1])) for l in proc.stdout.readlines() if b'systm' in l]

def restart_program():
    """Restarts the current program, with file objects and descriptors
       cleanup
    """

    try:
        p = psutil.Process(os.getpid())
        fds = p.open_files() + p.connections()
        print (fds)
        for handler in fds:
            os.close(handler.fd)
    except Exception as e:
        logging.error(e)

    python = sys.executable
    os.execl(python, python, *sys.argv)

它不漂亮,但它有效。

如果有人能对实际情况/正在发生的事情有所了解,我非常想知道。

标签: pythonunixlsofpython-3.7basehttpserver

解决方案


嗯,这看起来像是一种非常骇人听闻的方式来重新启动进程,而且总的来说是个坏主意。你的用例是什么?为什么要重新启动一个进程?无论您的动机如何,在这种意义上与流程交互的通常方式是通过信号。我不知道专门设计用于重新启动进程的信号。您通常想要做的是终止它(SIGTERM),并且可能有诸如 systemd 或 zdaemon 之类的东西会自动重新启动它。您甚至可以编写一个信号处理程序来在 SIGTERM 上执行清理功能,是进行清理的正确方法。不过,您通常不想重新启动进程,更不用说从应用程序本身进行了。这看起来像是麻烦的秘诀。


推荐阅读