在Python 3中从CGI输出二进制数据

ast*_*nlu 4 python cgi binary-data python-3.x

这个问题关系到这一个.从Python 2中的CGI脚本打印原始二进制数据时,我没有遇到任何问题,例如:

#!/usr/bin/env python2

import os

if __name__ == '__main__':
    with open(os.path.abspath('test.png'), 'rb') as f:
        print "Content-Type: image/png\n"
        print f.read()
Run Code Online (Sandbox Code Playgroud)

以下是相关的响应标头:

> GET /cgi-bin/plot_string2.py HTTP/1.1
> User-Agent: curl/7.32.0
> Host: 0.0.0.0:8888
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 Script output follows
< Server: SimpleHTTP/0.6 Python/3.3.2
< Date: Fri, 13 Sep 2013 16:21:25 GMT
< Content-Type: image/png
Run Code Online (Sandbox Code Playgroud)

并且结果被解释为图像,如预期的那样.但是,如果我尝试翻译Python 3:

#!/usr/bin/env python

import os
import sys

if __name__ == '__main__':
    with open(os.path.abspath('test.png'), 'rb') as f:
        print("Content-Type: image/png\n")
        sys.stdout.buffer.write(f.read())
Run Code Online (Sandbox Code Playgroud)

没有返回任何内容,以下是标题:

> GET /cgi-bin/plot_string3.py HTTP/1.1
> User-Agent: curl/7.32.0
> Host: 0.0.0.0:8888
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 Script output follows
< Server: SimpleHTTP/0.6 Python/3.3.2
< Date: Fri, 13 Sep 2013 16:22:13 GMT
< ?PNG
< 
Run Code Online (Sandbox Code Playgroud)

我不能再做print(f.read())了,因为那会打印出类似的东西b'\x89PNG\r\n\x1a\n\x00....我链接的问题提供了一个解决方案,但显然在这种环境中不起作用.

思考?

补充:未来注意事项:

这也意味着printCGI不再有用.

fal*_*tru 14

使用sys.stdout.flush以迫使身体之前打印头:

import os
import sys

if __name__ == '__main__':
    with open(os.path.abspath('test.png'), 'rb') as f:
        print("Content-Type: image/png\n")
        sys.stdout.flush() # <---
        sys.stdout.buffer.write(f.read())
Run Code Online (Sandbox Code Playgroud)

或删除打印,sys.stdout.buffer.write仅使用:

import os
import sys

if __name__ == '__main__':
    with open(os.path.abspath('test.png'), 'rb') as f:
        sys.stdout.buffer.write(b"Content-Type: image/png\n\n") # <---
        sys.stdout.buffer.write(f.read())
Run Code Online (Sandbox Code Playgroud)

注意

f.read()如果文件很大,可能会导致问题.为防止这种情况,请使用shutil.copyfileobj:

import os
import shutil
import sys

if __name__ == '__main__':
    with open(os.path.abspath('test.png'), 'rb') as f:
        sys.stdout.buffer.write(b"Content-Type: image/png\n\n")
        shutil.copyfileobj(f, sys.stdout.buffer)
Run Code Online (Sandbox Code Playgroud)