I have the following request file that is called when running a wsgiref server:
import cgi, os
import cgitb; cgitb.enable()
import pdb, time
STATUS_TEXT = \
{
200: 'OK',
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
409: 'Conflict'
}
class AmyTest( object ):
def __init__( self, env, start_response ):
"""
rootDir_ is used to have the path just in case you need to refer to
files in the directory where your script lives
environ_ is how most things are passed
startReponse_ is WSGI interface for communicating results
"""
self.rootDir_ = os.environ.get( 'ROOT_DIR', ',' )
self.environ_ = env
self.startResponse_ = start_response
def doTest( self ):
method = self.environ_.get( 'REQUEST_METHOD', 'get' ).lower()
if method == 'post':
params = cgi.FieldStorage(
fp = self.environ_[ 'wsgi.input' ],
environ = self.environ_, keep_blank_values = True
)
else:
params = cgi.FieldStorage(
environ = self.environ_, keep_blank_values = True
)
vehicle_type = params.getfirst( 'vehicletype' )
power_train_type = params.getfirst( 'powertraintype' )
engine_displacement = params.getfirst( 'enginedisplacement' )
engine_power = params.getfirst( 'enginepower' )
curb_weight = params.getfirst( 'curbweight' )
gv_weight = params.getfirst( 'gvweight' )
frontal_area = params.getfirst( 'frontalarea' )
coefficient_adrag = params.getfirst( 'coad' )
rr_coefficient = params.getfirst( 'rrco' )
sat_options = params.getfirst( 'satoptions' )
# This is the response HTML we are generating.
fmt = """
<h2>Results</h2>
<table>
<tr><td>Vehicle Type:</td><td>%s</td></tr>
<tr><td>Power Train Type:</td><td>%s</td></tr>
<tr><td>Engine Displacement (L):</td><td>%s</td></tr>
<tr><td>Engine Power (hp):</td><td>%s</td></tr>
<tr><td>Curb Weight (lbs):</td><td>%s</td></tr>
<tr><td>Gross Vehicle Weight Rating (lbs):</td><td>%s</td></tr>
<tr><td>Frontal Area (m^2):</td><td>%s</td></tr>
<tr><td>Coefficient of Aerodynamic Drag:</td><td>%s</td></tr>
<tr><td>Rolling Resistance Coefficient:</td><td>%s</td></tr>
<tr><td>Selected Advanced Technology Options:</td><td>%s</td></tr>
</table>
"""
content = fmt % ( vehicle_type, power_train_type, engine_displacement, engine_power, curb_weight, gv_weight, frontal_area, coefficient_adrag, rr_coefficient, sat_options)
headers = \
[
# ( 'Content-disposition',
# 'inline; filename="%s.kmz"' % excat_in[ 'name' ] )
]
result = \
{
'body': content,
'code': 200,
'headers': headers,
'type': 'text/html'
}
time.sleep(5)
return result
def process( self ):
result = self.doTest()
return self.sendResponse( **result )
def sendResponse( self, **kwargs ):
"""
@param body
@param code
@param headers
@param type
"""
code = kwargs.get( 'code', 200 )
status = '%d %s' % ( code, STATUS_TEXT[ code ] )
body = kwargs.get( 'body', '' )
mime_type = kwargs.get( 'type', 'text/plain' )
headers = \
[
( 'Content-Length', str( len( body ) ) ),
( 'Content-Type', mime_type )
]
headers_in = kwargs.get( 'headers' )
if headers_in != None and len( headers_in ) > 0:
headers += headers_in
self.startResponse_( status, headers )
return [body]
@staticmethod
def processRequest( env, start_response ):
server = AmyTest( env, start_response )
return server.process()
Everything works fine on Python 2 but when I try to run on Python 3 I get errors about write() argument must be bytes instance and NoneType object is not subscriptable. Errors from the console are:
Traceback (most recent call last):
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 138, in run
self.finish_response()
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 180, in finish_response
self.write(data)
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 266, in write
"write() argument must be a bytes instance"
AssertionError: write() argument must be a bytes instance
Traceback (most recent call last):
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 141, in run
self.handle_error()
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 368, in handle_error
self.finish_response()
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 180, in finish_response
self.write(data)
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 274, in write
self.send_headers()
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 331, in send_headers
if not self.origin_server or self.client_is_modern():
File "/Users/gavin/miniconda3/lib/python3.6/wsgiref/handlers.py", line 344, in client_is_modern
return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable
Any suggestions on how to get this working in Python 3 would be very helpful.
The
write()function expecting bytes can be fixed by callingyour_arg.encode(), ifyour_argis a string. Theencode()function converts a string to bytes, anddecode()will convert bytes to a string.The encode/decode functions are not available in python 3, converting bytes to strings and vice versa is handled differently in python 2.
The other error saying not subscriptable means it doesn't support subscript notation. E.g.
foo[i]. So where you're getting that error, that object doesn't support[]subscripting.