<html>
<head>
</head>
<body>
<form action="http://localhost:9000/cgi/cgi-test.py"
enctype="multipart/form-data"
method="post">
<label>File</label><br/>
<input type="file" name="contents"> <br/>
<button type="submit" >Submit</button> <br/>
</form>
</body>
</html>
cgi-test.py:
#!/usr/local/bin/python3
import cgi
import sys
form = cgi.FieldStorage()
print(form.getfirst('contents'), file=sys.stderr)
print('done')
I run a CGI server with:
#!/usr/bin/env python3
from http.server import HTTPServer, CGIHTTPRequestHandler
HTTPServer(('', 9000), CGIHTTPRequestHandler).serve_forever()
What happens is that the upload never stops. It works in 2.6.
If I cancel the upload from the browser, I get the following output,
so I know that basically things are working;
the cgi script just never finishes reading the POST input:
localhost - - [02/Mar/2010 16:37:36] "POST /cgi/cgi-test.py HTTP/1.1"
200 -
<<<CONTENTS OF MY FILE PRINTED HERE>>>
----------------------------------------
Exception happened during processing of request from ('127.0.0.1',
55779)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/socketserver.py", line 281, in _handle_request_noblock
self.process_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/socketserver.py", line 307, in process_request
self.finish_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/socketserver.py", line 320, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/socketserver.py", line 614, in __init__
self.handle()
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/http/server.py", line 352, in handle
self.handle_one_request()
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/http/server.py", line 346, in handle_one_request
method()
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/http/server.py", line 868, in do_POST
self.run_cgi()
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/http/server.py", line 1045, in run_cgi
if not self.rfile.read(1):
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/
python3.1/socket.py", line 214, in readinto
return self._sock.recv_into(b)
socket.error: [Errno 54] Connection reset by peer
----------------------------------------
> Can someone tell me how to upload the contents of a (relatively
> small) file using an HTML form and CGI in Python 3.1? As far as I
> can tell from a half-day of experimenting, browsing, and searching
> the Python issue tracker, this is broken.
followed by a detailed example demonstrating the problem.
Having hear no response, let me clarify that this request was
preliminary to filing a bug report -- I wanted to make sure I wasn't
missing something here. If nothing else, this failure should be
documented rather than the 3.1 library documentation continuing to
describe how to upload file contents with POST. If someone thinks
there is a way to make this work in 3.1, or that it isn't a bug
because CGI is hopeless (i.e., non-WSGI-compliant), or that the
documentation shouldn't be changed, please respond. I'd rather have
this particular discussion here than in the bug tracking system.
Meanwhile, let me heartily recommend the Bottle Web Framework (http://bottle.paws.de
) for its simplicity, flexibility, and power. Very cool stuff. To make
it work in Python3.1, do the following:
1. run 2to3 on bottle.py (the only file there is to download)
2. copy or move the resulting bottle.py to the site-libs directory in
your Python installation's library directory
3. don't use request.GET.getone or request.POST.getone -- instead of
getone, use get (the protocol changed to that of the Mapping ABC from
the collections module)
4. the contents of a file will be returned inside a cgi.FieldStorage
object, so you need to add '.value' after the call to get in that case