截断的输出使用Python瓶0.12.8作为Apache服务器上Windows下的CGI应用程序

这是应用程序:

#!/home2/friendv0/Python-2.7.9/bin/python from bottle import Bottle app = Bottle() @app.get('/') def hello(): return """<!DOCTYPE html> <html lang="en"> <head> <title>bottle Test</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8"> </head> <body> Hello! </body> </html> """ app.run(server='cgi') 

结果输出是:

 <!DOCTYPE html> <html lang="en"> <head> <title>bottle Test</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8"> </head> <body> Hello! </body> 

请注意,结束</ html>标记缺失。 只有当应用程序在Windows 7(或Windows 8)下作为CGI脚本运行时(而不是作为本机WSGI应用程序安装时)才会发生这种情况。 我已经用Apache 2.2和Apache 2.4试了这个。 请注意,在运行Apache 2.2的Linux系统上安装相同的CGI脚本时不会截断。 令人费解的是,我已经成功运行其他WSGI应用程序作为Windows下的CGI脚本,而不会使用瓶子使用的相同技术截断,即:

 from wsgiref.handlers import CGIHandler CGIHandler().run(application) 

有没有人遇到同样的问题? 作为一个方面说明:我有兴趣作为一个CGI脚本运行瓶的原因是因为我的预期音量非常低,所以性能不会是一个问题。 但是在Linux服务器(幸运的是,CGI正在工作),我没有能力重新启动服务器,如果必须对源代码进行紧急更改,我需要立即生效。

那么,我已经找出了这个问题。 字符串文字长度为201个字符(标题中的内容长度)。 每行都由一个LF(换行符)字符来终止(即使在Windows上,实际文本也是以CRLF结尾的)。 然而,当文本被发送到浏览器时,每行结尾现在是一个CR-LF对,使得实际输出长于201个字符,但是由于在标题中设置了内容长度,所以存在截断。 我回到了另一个正在工作的WSGi-CGI应用程序,现在请记住,因为有些情况下我发送图像,所以我已经将stdout流设置为二进制模式(在Unix / Linux上不需要)。 这显然有防止额外的回车字符插入文本流的副作用,如果我有模板没有他们开始。 所以,现在我有以下代码:

 import os if os.name == 'nt': import msvcrt msvcrt.setmode(0, os.O_BINARY ) # 0 = sysin msvcrt.setmode(1, os.O_BINARY ) # 0 = stdout app.run(server='cgi') 

是的,我在Flask应用程序中遇到了同样的问题:Windows平台上的Python 2.7.13 CGIHandler(mod_cgi),Apache 2.2。
解决方案已经确认! 这是一个测试脚本:

 #!C:/Python27/python.exe # -*- coding: utf-8 -*- import os if os.name == 'nt': import msvcrt msvcrt.setmode( sys.stdin.fileno(), os.O_BINARY ) msvcrt.setmode( sys.stdout.fileno(), os.O_BINARY ) msvcrt.setmode( sys.stderr.fileno(), os.O_BINARY ) from wsgiref.handlers import CGIHandler def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['Hello World!\nXMX\nYMY\n'] if __name__ == '__main__': CGIHandler().run( application ) 

没有msvcrt.setmode输出将被截断。
与WSGI(mod_wsgi)相同的应用程序正常工作。
在POSIX系统上没有CGI问题。
另一个解决方案是把Python放在“非缓冲模式”中,在解释器指令中加入-u参数:

 #!C:/Python27/python.exe -u # -*- coding: utf-8 -*- from wsgiref.handlers import CGIHandler def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['Hello World!\nXMX\nYMY\n'] if __name__ == '__main__': CGIHandler().run( application ) 

Python文档参考说:

-u强制stdin,stdout和stderr完全无缓冲。 在重要的系统上,也可以把stdin,stdout和stderr放在二进制模式下。