Python Twisted 中非阻塞的 INotify

1 投票
2 回答
1805 浏览
提问于 2025-04-16 18:45

我正在使用twisted的INotify来监控/dev目录,以便观察是否有新的串口设备被添加。现在我用的代码大致如下。

notifier = INotify()
notifier.watch(FilePath("/dev"), IN_CREATE, callbacks=[self.created])
notifier.startReading()

def created(self, ignored, path, mask):
    ...
    blocking code
    ...

我目前遇到的问题是,当'created'这个方法被调用时,它会阻塞我的反应器,这样其他的网络会话(我有TCP和UDP连接都和同一个反应器关联)就得等着'created'方法执行完才能继续。

有没有人知道我该怎么做才能让'created'方法在后台运行,这样就不会阻塞我的反应器了?

谢谢,

西蒙

2 个回答

1

你可以使用 twisted.internet.threads.deferToThread 来在一个线程中运行你的阻塞代码:

deferToThread(self.created, ignored, path mask)
7

在Twisted中,所有的事件处理程序都在“反应线程”中运行,包括UDP、TCP,以及inotify。它们都需要和系统合作,避免阻塞。因此,从这个角度来看,这其实是关于如何在Twisted中编写良好事件处理程序的问题,而不是特别针对inotify。

有很多方法可以避免阻塞。回答你的问题有点棘手,因为合适的选择取决于当前代码为什么会阻塞。

如果它在进行套接字输入输出(I/O)操作?那就使用Twisted的非阻塞套接字I/O接口。

如果它在进行文件系统I/O操作?你可能需要使用线程,因为没有线程的情况下,非阻塞的文件系统I/O是比较困难的(可能不是不可能)。

如果它在和SQL数据库通信?也许twisted.enterprise.adbapi可以帮上忙。

还有其他情况。

我不确定这是否涵盖了你的情况。不过,我想强调两点。首先,在Twisted程序中使用线程是完全合理的。Twisted的很多功能都是为了让你不必使用线程,但如果你遇到的情况是线程能解决问题而其他方法都不行,那就大胆使用吧(当然要小心;)。Twisted甚至提供了一些辅助工具来简化这个过程,比如zeekay提到的deferToThread。第二,选择适合任务的解决方案。所有“阻塞”问题的集合仅比所有通用编程问题的集合小一点。可能的解决方案有很多。有些,比如线程,似乎适用范围很广,但稍加留意,你可能会找到更适合特定情况的解决方案。

另外,可以看看Twisted:让代码非阻塞,以获取更多解释。

撰写回答