希望您能帮助我。它将需要一些解释...
TLDR问题:为什么线程进程会从myprocess.start()
之类的交互模式按预期方式运行(分离的python线程)却从{{1}这样的shell运行时会阻塞子线程}?
背景:我为类python myprocess.py
继承了子类,该类也调用了另外两个threading.Thread
类型的子类。看起来像:
Thread
这两个服务(class Node(threading.Thread):
def __init__(self, gps_device):
threading.Thread.__init__(self)
self.daemon = False
logging.info("Setting up GPS service")
self.gps_svc = gps.CoordinateService(gps_device)
self.gps_svc.daemon = True
logging.info("Setting up BLE scanning service")
# TODO: This is blocking when run in terminal (aka how we do on Raspberry Pi)
self.scan_svc = scan.BleMonitor()
self.scan_svc.daemon = True
logging.info("Node initialized - ready for start")
def run(self):
self.gps_svc.start()
self.scan_svc.start() # blocks here in terminal
do stuff...
和gps_svc
)都按照解释器的意图以交互方式(如scan_svc
)正常工作。当我使用脚本调用解释器时,node = Node(...); node.start()
启动并起作用,但是gps_svc
在侦听蓝牙设备的特定行处阻塞。
BLE扫描器在下面(它很长)。这是scan_svc
的父类-没什么不同,我只添加了几个实用程序函数。
问题:为什么会这样?我可以与PROCESS而不是BleMonitor
运行/交互(即:类的调用方法并实时获取数据)吗?
Thread
答案 0 :(得分:1)
在Python Documentation中,我认为交互式模式下的解释器在涉及线程时违反了以下条件:
在CPython中,全局解释器锁(即GIL)是一个互斥体,用于保护对Python对象的访问,从而防止多个线程一次执行Python字节码。锁定是必要的,主要是因为CPython的内存管理不是线程安全的。 (但是,由于存在GIL,因此其他功能也逐渐依赖于它所执行的保证。)
因此,存在这样的规则:只有获得GIL的线程才可以在Python对象上操作或调用Python / C API函数。为了模拟执行的并发性,解释器会定期尝试执行以下操作:切换线程(请参阅sys.setswitchinterval())。该锁定也释放在可能阻止诸如读取或写入文件之类的I / O操作的周围,以便其他Python线程可以同时运行。
我需要进一步研究,但是我的怀疑使我想到了GIL与线程对象管理之间的冲突。希望对您有所帮助或有人可以添加更多内容。