Fun with IO

Frank Millman frank at chagford.com
Fri Jan 17 01:01:33 EST 2020


Hi all

I just tried something that I did not think had a snowball's chance of 
working, but to my surprise it did. I thought I would share it, partly 
for interest, and partly in case anyone can foresee any problems with it.

I use ReportLab to generate pdf files. I do not write them to disk, but 
use BytesIO to store them in memory. There are two main scenarios - send 
an email and attach a pdf (which I have not addressed yet), and stream a 
pdf via HTTP for display in a browser (which is the subject of this post).

I use asyncio, which accepts a request from a client and passes a 
client_reader and a client_writer to my handler. This is how I handle a 
pdf request at present -

     with io.BytesIO() as pdf_fd:
         await pdf_handler(pdf_fd)
         pdf_fd.seek(0)  # rewind
         client_writer.write(pdf_fd.read())
     client_writer.write(b'\r\n')

I actually write it in 'chunks', but omitted that to keep it simple.

It works perfectly. However, some pdf's can be large, and there could be 
concurrent requests, so I wanted to minimise the memory footprint. So I 
tried passing the client_writer directly to the handler -

     await pdf_handler(client_writer)
     client_writer.write(b'\r\n')

It works! ReportLab accepts client_writer as a file-like object, and 
writes to it directly. I cannot use chunking, so I just let it do its thing.

Can anyone see any problem with this?

Thanks

Frank Millman


More information about the Python-list mailing list