2017-10-18 9 views
1

プログラムをTornadoからAsyncioに変換しようとしていますが、最初のステップは実際のasyncioイベントループをdescribed hereとして使用することです。Python Asyncioを使用してGPIO割り込みを待ちます

このアプリケーションは組み込みLinuxマシン上で動作し、私はsysfs/gpio subsystemを通してGPIOを使用しています。これらのGPIOの中には、割り込みを待っているものがあります。私が直接行って、トルネードIOLoopにこれを統合することができました:

コードピースで
# Register with the queue 
self.io_loop.add_handler(
    self.gpio._value_file, self._handle_interrupt, self.io_loop._EPOLLPRI | self.io_loop.ERROR 
) 

_value_fileはGPIOから読み取ることができるファイルへのファイルハンドルです。 EPOLLPRIイベントは、そのGPIO上の割り込みが使用可能なときはいつでも起動されます。トルネードでは、これは非常にうまくいく。割り込みが来た直後に_handle_interrupt関数を呼び出します。

私の問題は、これをネイティブasyncioイベントループに変換できなかったことです。 the documentation for watching file descriptors私は読者とライターを追加する機能しか見つけられませんが、ファイル記述子の汎用イベントマスクを監視する機能はありません。それはしかし、C.に入るので、私はこれがそうであるようにそれはそうasyncio IOLoopにトルネードIOLoopからの呼び出しを翻訳するためにトルネード層を見て、コードに飛び込むことができません。

def add_handler(self, fd, handler, events): 
    fd, fileobj = self.split_fd(fd) 
    if fd in self.handlers: 
     raise ValueError("fd %s added twice" % fd) 
    self.handlers[fd] = (fileobj, stack_context.wrap(handler)) 
    if events & IOLoop.READ: 
     self.asyncio_loop.add_reader(
      fd, self._handle_events, fd, IOLoop.READ) 
     self.readers.add(fd) 
    if events & IOLoop.WRITE: 
     self.asyncio_loop.add_writer(
      fd, self._handle_events, fd, IOLoop.WRITE) 
     self.writers.add(fd) 

読み取り専用とWRITEフラグは変換され、他のすべてのフラグは無視されます。

誰かが、現在、asyncioを使用して、READおよびWRITEイベント以外のファイルディスクリプタのイベントを監視できないことを確認できますか?あるいは私は何か間違っているのですか?実際に方法がありますか?

答えて

2

私は今この解決策を見つけました。私の主な情報源はthis thread in the Python-tulip groupthis piece of codeでした。

POLLPRIイベントを監視するために使用できるepoll自体がファイル記述子です。 epollが監視するFD上でイベントが発生するたびに、epollファイル記述子はPOLLINイベントを生成し、add_readerでasyncioを使用して監視することができます。だからではなく、直接登録する、我々は手動でのepoll構造を作成し、そのようなioloopに登録:

self.epoll = select.epoll() 
self.io_loop.add_reader(self.epoll.fileno(), self._handle_interrupt) 

実際の割り込みイベントは、その後、この時点でのepoll構造

self.epoll.register(self.gpio._value_file, select.POLLPRI) 

に登録されています割り込みイベントは_handle_interruptファンクションで受信されます。実際にイベントハンドラでのepoll構造をポーリングすることを確認し、またはそれは継続的に彼らは同様の操作を行うため、高レベルselectorsの代わりに低レベルselect機能を使用することが重要である読み取りイベント

def _handle_interrupt(self): 
    self.epoll.poll(0) 
    ... 

を生成します。 asyncioのようなイベントフラグフィルタリング。次のコード切り取らselectors.EpollSelectorからです:

def register(self, fileobj, events, data=None): 
    key = super().register(fileobj, events, data) 
    epoll_events = 0 
    if events & EVENT_READ: 
     epoll_events |= select.EPOLLIN 
    if events & EVENT_WRITE: 
     epoll_events |= select.EPOLLOUT 
    try: 
     self._epoll.register(key.fd, epoll_events) 
    except BaseException: 
     super().unregister(fileobj) 
     raise 
    return key 

READとWRITEを除くすべてのイベントがフィルタリングされていること、見ることができます。したがって、高水準インタフェースを使用してPOLLPRIイベントを監視することはできません。したがって、低レベルのインタフェースを使用してください。

私は、これが人々がこの問題につまずかせるのを助けることを望みます。

関連する問題