【问题标题】:Output binary data from CGI in Python 3在 Python 3 中从 CGI 输出二进制数据
【发布时间】:2013-09-13 16:25:36
【问题描述】:

此问题与this one 有关。从 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()

以下是相关的响应标头:

> 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

并且结果被解释为图像,正如预期的那样。但是,如果我尝试翻译成 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())

没有返回任何内容,这里是标题:

> 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
< 

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

想法?

添加Note for the future

这也意味着print 不再适合 CGI。

【问题讨论】:

    标签: python python-3.x cgi binary-data


    【解决方案1】:

    使用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())
    

    或删除打印,并仅使用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())
    

    注意

    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)
    

    【讨论】:

    • 天哪,谢谢你。无法相信让它发挥作用有多么困难
    猜你喜欢
    • 2010-10-28
    • 2016-06-17
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    • 2011-10-04
    • 2019-09-04
    • 2016-12-16
    • 2014-09-02
    相关资源
    最近更新 更多