#python #raspberry-pi
#python #raspberry-pi
Вопрос:
У меня есть плата PiFace, установленная на моем Raspberry Pi, и я хочу завершить свою программу на Python, когда я нажимаю кнопку 3. Поэтому я подключаю прослушиватель прерываний к этой кнопке и вызываю loop.stop() в обратном вызове, но мой цикл не останавливается. Как будто мои команды игнорируются.
Мой код:
#!/usr/bin/python3
import pifacedigitalio as piface
import asyncio
import time
QUIT_DETECT = 3
loop = asyncio.get_event_loop()
counter = 0
def onQuit(event):
# Doesn't stop
global loop
loop.stop()
print(loop)
# Does change
global counter
counter = 1
print(counter)
piface.init()
listener = piface.InputEventListener()
listener.register(QUIT_DETECT, piface.IODIR_FALLING_EDGE, onQuit)
listener.activate()
loop.run_forever()
loop.close()
listener.deactivate()
piface.deinit()
Вывод таков:
<_UnixSelectorEventLoop running=True closed=False debug=False>
1
<_UnixSelectorEventLoop running=True closed=False debug=False>
2
<_UnixSelectorEventLoop running=True closed=False debug=False>
3
<_UnixSelectorEventLoop running=True closed=False debug=False>
4
So counter
увеличивается при каждом нажатии, но loop
просто не принимает мой вызов stop. Кто-нибудь может сказать мне, как остановить цикл? Заранее спасибо
Комментарии:
1. вы уверены, что asyncio должен запускаться на raspberry-pi? (возможно, это не raspberry-py по какой-то причине : D)
2. @vlad-ardelean Я полагаю, что да. Почему бы и нет? Тем временем я попробую обходной путь с
Barrier
объектом.
Ответ №1:
Я предполагаю, что у вас запущены некоторые сопрограммы и вы выполняете некоторую работу, потому что в этом фрагменте нет необходимости в asyncio, он просто не используется для блокировки…
Тем не менее, я совершенно уверен, что у вас есть проблема с потоками.
Смотрю на GitHub в модулях:
piface.InputEventListener()
получает из pifacecommon.прерывает.PortEventListener
class InputEventListener(pifacecommon.interrupts.PortEventListener):
PortEventListener использует потоковую обработку и многопроцессорность
import threading
import multiprocessing
[....]
class PortEventListener(object):
"""Listens for port events and calls the registered functions.
>>> def print_flag(event):
... print(event.interrupt_flag)
...
>>> port = pifacecommon.mcp23s17.GPIOA
>>> listener = pifacecommon.interrupts.PortEventListener(port)
>>> listener.register(0, pifacecommon.interrupts.IODIR_ON, print_flag)
>>> listener.activate()
"""
TERMINATE_SIGNAL = "astalavista"
def __init__(self, port, chip, return_after_kbdint=True, daemon=False):
self.port = port
self.chip = chip
self.pin_function_maps = list()
self.event_queue = EventQueue(self.pin_function_maps)
self.detector = multiprocessing.Process(
target=watch_port_events,
args=(
self.port,
self.chip,
self.pin_function_maps,
self.event_queue,
return_after_kbdint))
self.detector.daemon = daemon
self.dispatcher = threading.Thread(
target=handle_events,
args=(
self.pin_function_maps,
self.event_queue,
_event_matches_pin_function_map,
PortEventListener.TERMINATE_SIGNAL))
self.dispatcher.daemon = daemon
кажется, выполняется в другом потоке и вызывает вас обратно. Очевидно, что остановка не достигает asyncio.цикл в основном потоке.
Согласен, пока?
В идеале вы должны использовать либо потоковое, либо асинхронное программирование в одном потоке.
Тем не менее, я ожидаю, что передача ссылки на цикл вместо ее глобального использования сработает: def onQuit (цикл):
listener.register(QUIT_DETECT, piface.IODIR_FALLING_EDGE, onQuit(loop))
или
из functools частично импортируется
listener.register(ЗАВЕРШАЕТ ОБНАРУЖЕНИЕ, piface.IODIR_FALLING_EDGE, частичное (завершение, цикл))
Вы пытались повторно запустить цикл вместо глобального использования в onQuit? asyncio.get_event_loop()
Веселись, Дэнни