Why does Paste ErrorMiddleware throw an exception when I use it with my Python 3 mod_wsgi application?

317 views Asked by At

I am trying to use the ErrorMiddleware included in Python Paste 2.0.3 in order to show tracebacks in the browser when my Python 3.4 mod_wsgi application server throws an exception. The issue I am having is that the ErrorMiddleware is throwing this exception whenever it attempts to handle my server's exceptions:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.4/site-packages/paste/exceptions/errormiddleware.py", line 154, in __call__
    response = self.exception_handler(exc_info, environ)
  File "/usr/lib/python3.4/site-packages/paste/exceptions/errormiddleware.py", line 188, in exception_handler
    simple_html_error=simple_html_error)
  File "/usr/lib/python3.4/site-packages/paste/exceptions/errormiddleware.py", line 391, in handle_exception
    error_stream.write(line)
TypeError: must be str, not bytes

and so I am still just getting 500 Internal Server Error in the browser.

The issue seems to be that the ErrorMiddleware is trying to write bytes to the wsgi error stream:

    if six.PY3:
        line = line.encode('utf8')
    error_stream.write(line) # line 391 error_stream comes from environ['wsgi.errors']

but if I print out environ['wsgi.errors'] it appears to be a text stream:

'wsgi.errors': <_io.TextIOWrapper name='<wsgi.errors>' encoding='utf-8'>

which means the ErrorMiddleware can't write bytes to it.

I am wrapping my application in the ErrorMiddleware like this:

application = ErrorMiddleware(application, debug=True)

Is there something I am doing wrong to cause this? Can I configure mod_wsgi so that the error stream is a byte stream instead of a text stream?

1

There are 1 answers

1
Graham Dumpleton On BEST ANSWER

The wsgi.errors should notionally behave the same as writing to sys.stdout.

$ python3.6
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.write('hello\n')
hello
6
>>> sys.stdout.write(b'hello\n')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: write() argument must be str, not bytes

So it looks wrong that they would attempt to write bytes on Python 3.