jdowner
jdowner

Reputation: 736

Reading from asyncio StreamReader

I am trying to extend the python asyncio HTTP server example that uses a streaming reader/writer (code). If I understand it correctly, the example handler read 100 bytes from the reader and echoes it back to the client through the writer. I am trying to read more than 100 bytes... reading until there is nothing more to read would be nice.

I have tried letting the read() function read as much as possible,

data = yield from reader.read()

but that seems to block forever. So I tried reading chunks until the EOF is reached,

while not reader.at_eof():
    data += yield from reader.read(100)

and while this retrieves more of the data, it to seems to block on the read call instead of exiting the while loop.

How can I get the entire message from the client using the stream reader?

Upvotes: 8

Views: 34315

Answers (4)

Oded BD
Oded BD

Reputation: 3276

A bit nicer way to do it in my opinion will be to put the condition in the while loop, like that:

data = bytearray()
while not stream.at_eof():
    chunk = yield from reader.read(1024)
    data += chunk

Upvotes: 0

Ytsen de Boer
Ytsen de Boer

Reputation: 3107

Like so:

empty_bytes = b''
result = empty_bytes

while True:
    chunk = await response.content.read(8)

    if chunk == empty_bytes:
        break

    result += chunk

To determine the EOF use

if chunk == empty_bytes:

in stead of

if not chunk:

See the docs (aiohttp): the read returns an empty byte string

b''

on EOF, so check for that explicitly.

Note: If you would like to read until the end of the chunk as it was delivered from the server, checkout

StreamReader.readchunk()

(Didn't test it, though.)

Upvotes: 3

Carlos Maniero
Carlos Maniero

Reputation: 67

Use feed_eof before at_eof.

request_text = b''
while True:
    request_text += yield from self.reader.read(1024)
    self.reader.feed_eof()
    if self.reader.at_eof():
        break

Upvotes: 0

Jashandeep Sohi
Jashandeep Sohi

Reputation: 5163

You should check if StreamReader.read returned an empty bytes object to signal an EOF:

data = bytearray()
while True:
    chunk = yield from reader.read(100)
    if not chunk:
        break
    data += chunk

Also, consider using aiohttp if you need a fully functional HTTP client.

Upvotes: 5

Related Questions