【问题标题】:Python gzip: is there a way to decompress from a string?Python gzip:有没有办法从字符串中解压缩?
【发布时间】:2010-12-05 08:17:13
【问题描述】:

我已经阅读了这个SO post 的问题,但无济于事。

我正在尝试解压缩来自 URL 的 .gz 文件。

url_file_handle=StringIO( gz_data )
gzip_file_handle=gzip.open(url_file_handle,"r")
decompressed_data = gzip_file_handle.read()
gzip_file_handle.close()

...但我得到 TypeError: coercing to Unicode: need string or buffer, cStringIO.StringI found

发生了什么事?

Traceback (most recent call last):  
  File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2974, in _HandleRequest
    base_env_dict=env_dict)
  File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 411, in Dispatch
    base_env_dict=base_env_dict)
  File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2243, in Dispatch
    self._module_dict)
  File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2161, in ExecuteCGI
    reset_modules = exec_script(handler_path, cgi_path, hook)
  File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2057, in ExecuteOrImportScript
    exec module_code in script_module.__dict__
  File "/home/jldupont/workspace/jldupont/trunk/site/app/server/tasks/debian/repo_fetcher.py", line 36, in <module>
    main()
  File "/home/jldupont/workspace/jldupont/trunk/site/app/server/tasks/debian/repo_fetcher.py", line 30, in main
    gziph=gzip.open(fh,'r')
  File "/usr/lib/python2.5/gzip.py", line 49, in open
    return GzipFile(filename, mode, compresslevel)
  File "/usr/lib/python2.5/gzip.py", line 95, in __init__
    fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb')
TypeError: coercing to Unicode: need string or buffer, cStringIO.StringI found

【问题讨论】:

  • 请从回溯中发布更多信息(哪一行失败)。
  • 用stringIO代替cStringIO能解决问题吗?
  • @recursive:我已经为 cStringIO 的可用性添加了必要的检查,如果没有,则恢复为 StringIO。

标签: python gzip


【解决方案1】:

您可以使用 gzip 内置 Python 库中的gzip.decompress(适用于 Python 3.2+)。

字节解压示例:

import gzip
gzip.decompress(gzip_data)

文档

https://docs.python.org/3.5/library/gzip.html#gzip.decompress

【讨论】:

    【解决方案2】:

    如果您不喜欢将晦涩的参数传递给zlib.decompress,请考虑使用gzip.GzipFile

    当您处理urllib2.urlopen 可以是 gzip 压缩或未压缩的响应时:

    import gzip
    from StringIO import StringIO
    
    # response = urllib2.urlopen(...
    
    content_raw = response.read()
    if 'gzip' in response.info().getheader('Content-Encoding'):
        content = gzip.GzipFile(fileobj=StringIO(content_raw)).read()
    

    当您处理可以存储 gzip 压缩或未压缩数据的文件时:

    import gzip
    
    # some_file = open(...
    
    try:
        content = gzip.GzipFile(fileobj=some_file).read()
    except IOError:
        some_file.seek(0)
        content = some_file.read()
    

    上面的例子在 Python 2.7 中

    【讨论】:

    • 在打开的 IO 缓冲区上使用 try/exceptread 并不是推断格式的最佳方法,因为每次尝试都可能消耗一些字节。
    【解决方案3】:

    如果您的数据已经在字符串中,请尝试 zlib,它声称与 gzip 完全兼容:

    import zlib
    decompressed_data = zlib.decompress(gz_data, 16+zlib.MAX_WBITS)
    

    阅读更多:http://docs.python.org/library/zlib.html

    【讨论】:

    • 这也是我一开始想到的。但很快发现它不起作用:“zlib.error: Error -3 while decompressing data: wrong header check”
    • 添加参数,使调用看起来像decompressed_data=zlib.decompress(gz_data, 16+zlib.MAX_WBITS),对我来说就像一个魅力。感谢这里stackoverflow.com/a/2695575/3635816
    【解决方案4】:

    gzip.open是打开文件的简写,你想要的是gzip.GzipFile,你可以传递一个fileobj

    open(filename, mode='rb', compresslevel=9)
        #Shorthand for GzipFile(filename, mode, compresslevel).
    

    class GzipFile
       __init__(self, filename=None, mode=None, compresslevel=9, fileobj=None)
       #    At least one of fileobj and filename must be given a non-trivial value.
    

    所以这应该适合你

    gzip_file_handle = gzip.GzipFile(fileobj=url_file_handle)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 2011-08-18
      • 2012-01-20
      • 1970-01-01
      • 2015-02-06
      • 2010-11-24
      • 2013-12-15
      相关资源
      最近更新 更多