Python Twisted 中非阻塞的 INotify
我正在使用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 个回答
你可以使用 twisted.internet.threads.deferToThread
来在一个线程中运行你的阻塞代码:
deferToThread(self.created, ignored, path mask)
在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:让代码非阻塞,以获取更多解释。