TypeError: write() argument must be str, not bytes
web.py release: 0.40
Python release: 3.7.3 (Debian buster)
While porting a project from Python 2 to Python 3 (thanks for the 0.40 release!), I immediately encountered a bug in web.input(). Apparently, when a POST is sent by requests (as opposed to a web browser), web.py emits an error:
TypeError: write() argument must be str, not bytes
If debug is enabled, the default, then a stream of errors occur with the a similar error. See this issue for more information #448.
Sure enough, setting web.config.debug = False will prevent the stream of errors, yet the originating error still exists. (Also, I want error handling, I'll address that later).
The source of the error is in cgi.py, as it tries and copy the BytesIO object web.py created into a TemporaryFile that was created without wb+.
Here is the cgi.py write error:
https://github.com/python/cpython/blob/ef4ec6ed12d6c6200a85068f60483723298b6ff4/Lib/cgi.py#L704
Here is the web.py BytesIO creation:
| fp = BytesIO(d) | |
| a = cgi.FieldStorage(fp=fp, environ=e, keep_blank_values=1) |
I am able fix this by monkey patching cgi.py, as the source of the error is make_file:
https://github.com/python/cpython/blob/ef4ec6ed12d6c6200a85068f60483723298b6ff4/Lib/cgi.py#L814-L842
Here is a test case:
import cgi import web import json import tempfile urls = ( '/', 'index' ) class index: def POST(self): inputs = web.input() data = json.loads(web.data()) print(inputs, data) return "Hello, world!" def make_file(self): return tempfile.TemporaryFile("wb+") # Comment out this line to reproduce the error cgi.FieldStorage.make_file = make_file if __name__ == "__main__": # Comment this line to see the stream of errors. Note, make_file # also needs to be the default, not patched, version. web.config.debug = False app = web.application(urls, globals()) app.run()
You may test this with httpie:
$ http -v POST localhost:8080 a=b
One last comment, when monkey patching cgi.py, the debugging error page works again.
Is there anything else I can submit to help solve this?