Я использую python для взаимодействия аппаратного устройства с USB-интерфейсом с API-интерфейсом python, предоставляемого поставщиком, и я пытаюсь читать (пакеты usb) с устройства в отдельном потоке в бесконечном цикле (который отлично работает). Проблема в том, что мой основной цикл, кажется, никогда не получает запланированных снова (мой цикл чтения получает все внимание).Проблемы с расписанием в python
Код выглядит так же, как это:
from threading import Thread
import time
usb_device = 0
def usb_dump(usb_device):
while True:
#time.sleep(0.001)
packet = ReadUSBDevice(usb_device)
print "packet pid: %s" % packet.pid
class DumpThread(Thread):
def run(self):
usb_dump()
usb_device = OpenUSBDevice()
t = DumpThread()
t.start()
print "Sleep 1"
time.sleep(1)
print "End"
CloseUSBDevice(usb_device)
sys.exit(0)
(я мог вставить фактический код, но так как вам нужно аппаратное устройство, я полагаю, что это не поможет).
Я ожидаю, что этот код начнет сбрасывать пакеты USB примерно за секунду до того, как основной поток завершит работу всей программы. Однако все, что я вижу, это «Сон 1», а затем процедура usb_dump()
выполняется навсегда. Если я раскомментирую инструкцию «time.sleep (0.001)» во внутреннем цикле процедуры usb_dump()
, все начнет работать так, как я ожидаю, но тогда код python не сможет идти в ногу со всеми входящими пакетами :-(
продавец говорит мне, что это проблема питон планировщик, а не вина их API, и для этого мне не поможет:.
«Тем не менее, кажется, что вы испытываете некоторые нюансы при использовании многопоточности в Python по поместив time.sleep в поток DumpThread, вы явно сигнализируете системе потоковой передачи Python, чтобы отказаться от управления. В противном случае интерпретатор Python должен определить, когда переключать потоки, и обычно это делает после определенного количество команд байтового кода выполнено ».
Может кто-нибудь подтвердить, что проблема python здесь? Есть ли другой способ сделать элемент управления DumpThread? Любые другие идеи?
На заметках: Я знаю, что код выглядит уродливым. Я начал с примера кода от поставщика и сделал как можно меньше изменений, пока еще показываю свою точку зрения. Я решил, что они будут знакомы с их собственным примером ... Это вовсе не производственный код. –
Итак, если я предполагаю, что расширение поставщика C (которое лежит за вызовом ReadUSBDevice) не освобождает GIL (как следует), то добавление небольшого сна (как я пытался) заставит код работать должным образом, потому что теперь Я явно освобождаю GIL на каждой итерации. Это объясняет поведение, которое я вижу. Есть ли другой способ освободить GIL? Возможно, я смогу сделать, если это будет спать каждые 50 раундов? –
Ответственность вашего поставщика - освободить GIL, и вы не можете этого сделать. Как насчет использования объекта threading.Timer? Он автоматически реализует как семантику вашей функции (периодический опрос), так и вам не придется заботиться об их реализации. –