I wrote the AsyncFile class a while ago, the interface is simpler than low-level protocols.
The original code is here: https://github.com/l04m33/pyx/blob/dbaf121ab7bb9bbf04616a7285bcaba757682d03/pyx/io.py#L20
class AsyncFile: """A local file class for use with the ``asyncio`` module. ``loop`` should be the event loop in use. ``filename`` is the name of the file to be opened. ``fileobj`` should be a regular file-like object. ``mode`` is the open mode accepted by built-in function ``open``. If ``filename`` is specified, the named file will be opened. And if ``fileobj`` is specified, that file object will be used directly. You cannot specify both ``filename`` and ``fileobj``. This class can be used in a ``with`` statement. """ DEFAULT_BLOCK_SIZE = 8192 def __init__(self, loop=None, filename=None, fileobj=None, mode='rb'): if (filename is None and fileobj is None) or \ (filename is not None and fileobj is not None): raise RuntimeError('Confilicting arguments') if filename is not None: if 'b' not in mode: raise RuntimeError('Only binary mode is supported') fileobj = open(filename, mode=mode) elif 'b' not in fileobj.mode: raise RuntimeError('Only binary mode is supported') fl = fcntl.fcntl(fileobj, fcntl.F_GETFL) if fcntl.fcntl(fileobj, fcntl.F_SETFL, fl | os.O_NONBLOCK) != 0: if filename is not None: fileobj.close() errcode = ctypes.get_errno() raise OSError((errcode, errno.errorcode[errcode])) self._fileobj = fileobj if loop is None: loop = asyncio.get_event_loop() self._loop = loop self._rbuffer = bytearray() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() def fileno(self): return self._fileobj.fileno() def seek(self, offset, whence=None): if whence is None: return self._fileobj.seek(offset) else: return self._fileobj.seek(offset, whence) def tell(self): return self._fileobj.tell() def _read_ready(self, future, n, total): if future.cancelled(): self._loop.remove_reader(self._fileobj.fileno()) return try: res = self._fileobj.read(n) except (BlockingIOError, InterruptedError): return except Exception as exc: self._loop.remove_reader(self._fileobj.fileno()) future.set_exception(exc) return if not res:
l04m33
source share