压缩 JSON 通过 CGI 在 Python 中发送
Compressing JSON sent via CGI in Python
我目前正在开发的 webApp 需要客户端请求的大型 JSON 文件,使用 Python 在服务器上构建并发送回客户端。该解决方案是通过 CGI 实现的,并且在各个方面都可以正常工作。
在这个阶段,我只是采用各种技术来最小化发送回客户端的结果 JSON objects 的大小,大约为 5-10mb(无需详细说明,这或多或少是固定的,并且不能以任何方式延迟加载)。
我们使用的主机不支持 mod_deflate 或 mod_gzip,因此虽然我们无法将 Apache 配置为使用 .htaccess 在服务器上自动创建 gzip 内容,但我认为我们仍然可以只要 Content-encoding header 设置正确,就可以在客户端接收并解码。
我想知道实现此目标的最佳方法是什么。在 Python 中压缩一些东西是微不足道的。我已经知道该怎么做,但问题是:
我如何以这种方式压缩数据,将其打印到输出流以通过 CGI 发送既压缩又可读给客户端?
文件必须根据输入数据即时创建,因此不能选择存储预制文件和预压缩文件,并且必须通过 webApp 中的 xhr 接收它们。
我最初的实验是用 gzip 和 io.stringIO 压缩 JSON 字符串,然后将其打印到输出流,导致它以 Python 的正常字节格式打印,例如: b'\n\x91\x8c\xbc\xd4\xc6\xd2\x19\x98\x14x\x0f1q!\xdc|C\xae\xe0 等等,这使请求膨胀到正常大小的两倍...
我想知道是否有人可以在这里为我指明正确的方向,告诉我如何实现这一点,如果确实可行的话。
我希望我已经正确地阐明了我的问题。
谢谢。
我猜你使用 print()
(它首先将其参数转换为字符串,然后再将其发送到标准输出)或 sys.stdout
(它只接受 str 对象)。
要直接在 stdout 上写入,可以使用 sys.stdout.buffer
,一个支持字节对象的类文件对象:
import sys
import gzip
s = 'foo'*100
sys.stdout.buffer.write(gzip.compress(s.encode()))
给出有效的 gzip 数据:
$ python3 foo.py | gunzip
foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo
感谢 Valentin 和 Phillip 的回答!
我设法解决了这个问题,你们两个都为最终答案做出了贡献。事实证明这是多种因素的结合。
这是有效的最终代码:
response = json.JSONEncoder().encode(loadData)
sys.stdout.write('Content-type: application/octet-stream\n')
sys.stdout.write('Content-Encoding: gzip\n\n')
sys.stdout.flush()
sys.stdout.buffer.write(gzip.compress(response.encode()))
在切换到 sys.stdout 而不是使用 print 来打印 headers 并刷新它设法正确读取的流之后。这很好奇……总有更多东西要学。
再次感谢!
我目前正在开发的 webApp 需要客户端请求的大型 JSON 文件,使用 Python 在服务器上构建并发送回客户端。该解决方案是通过 CGI 实现的,并且在各个方面都可以正常工作。 在这个阶段,我只是采用各种技术来最小化发送回客户端的结果 JSON objects 的大小,大约为 5-10mb(无需详细说明,这或多或少是固定的,并且不能以任何方式延迟加载)。 我们使用的主机不支持 mod_deflate 或 mod_gzip,因此虽然我们无法将 Apache 配置为使用 .htaccess 在服务器上自动创建 gzip 内容,但我认为我们仍然可以只要 Content-encoding header 设置正确,就可以在客户端接收并解码。
我想知道实现此目标的最佳方法是什么。在 Python 中压缩一些东西是微不足道的。我已经知道该怎么做,但问题是: 我如何以这种方式压缩数据,将其打印到输出流以通过 CGI 发送既压缩又可读给客户端?
文件必须根据输入数据即时创建,因此不能选择存储预制文件和预压缩文件,并且必须通过 webApp 中的 xhr 接收它们。
我最初的实验是用 gzip 和 io.stringIO 压缩 JSON 字符串,然后将其打印到输出流,导致它以 Python 的正常字节格式打印,例如: b'\n\x91\x8c\xbc\xd4\xc6\xd2\x19\x98\x14x\x0f1q!\xdc|C\xae\xe0 等等,这使请求膨胀到正常大小的两倍...
我想知道是否有人可以在这里为我指明正确的方向,告诉我如何实现这一点,如果确实可行的话。 我希望我已经正确地阐明了我的问题。 谢谢。
我猜你使用 print()
(它首先将其参数转换为字符串,然后再将其发送到标准输出)或 sys.stdout
(它只接受 str 对象)。
要直接在 stdout 上写入,可以使用 sys.stdout.buffer
,一个支持字节对象的类文件对象:
import sys
import gzip
s = 'foo'*100
sys.stdout.buffer.write(gzip.compress(s.encode()))
给出有效的 gzip 数据:
$ python3 foo.py | gunzip
foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo
感谢 Valentin 和 Phillip 的回答! 我设法解决了这个问题,你们两个都为最终答案做出了贡献。事实证明这是多种因素的结合。 这是有效的最终代码:
response = json.JSONEncoder().encode(loadData)
sys.stdout.write('Content-type: application/octet-stream\n')
sys.stdout.write('Content-Encoding: gzip\n\n')
sys.stdout.flush()
sys.stdout.buffer.write(gzip.compress(response.encode()))
在切换到 sys.stdout 而不是使用 print 来打印 headers 并刷新它设法正确读取的流之后。这很好奇……总有更多东西要学。 再次感谢!