使用Python下载,提取和读取gzip文件

时间:2010-08-23 14:28:23

标签: python

我想在Python中下载,提取和迭代文本文件,而无需创建临时文件。

基本上,这个管道,但在python中

curl ftp://ftp.theseed.org/genomes/SEED/SEED.fasta.gz | gunzip | processing step

这是我的代码:

def main():
    import urllib
    import gzip

    # Download SEED database
    print 'Downloading SEED Database'
    handle = urllib.urlopen('ftp://ftp.theseed.org/genomes/SEED/SEED.fasta.gz')


    with open('SEED.fasta.gz', 'wb') as out:
        while True:
            data = handle.read(1024)
            if len(data) == 0: break
            out.write(data)

    # Extract SEED database
    handle = gzip.open('SEED.fasta.gz')
    with open('SEED.fasta', 'w') as out:
        for line in handle:
            out.write(line)

    # Filter SEED database
    pass

我不想使用process.Popen()或其他任何东西,因为我希望这个脚本与平台无关。

问题是Gzip库只接受文件名作为参数而不是句柄。 “管道”的原因是下载步骤只占用了大约5%的CPU,同时运行提取和处理会更快。


修改: 这不起作用,因为

  

“因为gzip压缩的方式   有效,GzipFile需要保存它   位置和前进和前进   向后翻阅压缩文件。   当“文件”是a时,这不起作用   来自远程的字节流   服务器;你所能做的就是   一次检索一个字节,而不是移动   通过数据来回传递   流。“ - dive into python

这就是我收到错误的原因

AttributeError: addinfourl instance has no attribute 'tell'

那么curl url | gunzip | whatever如何运作?

4 个答案:

答案 0 :(得分:9)

只是gzip.GzipFile(fileobj=handle)你将会在路上 - 换句话说,“Gzip库只接受文件名作为参数而不是句柄”并不是真的,你只需要使用{{ 1}}命名参数。

答案 1 :(得分:0)

我在搜索从URL下载gzip文件和解压缩文件的方法时发现了这个问题,但是我没有设法使可接受的答案在Python 2.7中起作用。

以下是对我有用的内容(改编自here):

import urllib2
import gzip
import StringIO

def download(url):
    # Download SEED database
    out_file_path = url.split("/")[-1][:-3]
    print('Downloading SEED Database from: {}'.format(url))
    response = urllib2.urlopen(url)
    compressed_file = StringIO.StringIO(response.read())
    decompressed_file = gzip.GzipFile(fileobj=compressed_file)

    # Extract SEED database
    with open(out_file_path, 'w') as outfile:
        outfile.write(decompressed_file.read())

    # Filter SEED database
    # ...
    return

if __name__ == "__main__":    
    download("ftp://ftp.ebi.ac.uk/pub/databases/Rfam/12.0/fasta_files/RF00001.fa.gz")

由于原始URL已死,所以我更改了目标URL:我只是从ftp服务器中寻找了一个gzip文件,就像原始问题一样。

答案 2 :(得分:0)

一种python3解决方案,它不需要,不需要for循环并直接将byte对象写为binary流:

import gzip
import urllib.request

    def download_file(url):
       out_file = '/path/to/file'

       # Download archive
       try:
          # Read the file inside the .gz archive located at url
          with urllib.request.urlopen(url) as response:
             with gzip.GzipFile(fileobj=response) as uncompressed:
                file_content = uncompressed.read()

          # write to file in binary mode 'wb'
          with open(out_file, 'wb') as f:
             f.write(file_content)
             return 0

       except Exception as e:
          print(e)
          return 1

使用retval=download_file(url)调用函数以捕获return code

答案 3 :(得分:0)

对于python 3.8,这是我的代码,写于08/05/2020

import re
from urllib import request
import gzip
import shutil

url1 = "https://www.destinationlighting.com/feed/sitemap_items1.xml.gz"
file_name1 = re.split(pattern='/', string=url1)[-1]
r1 = request.urlretrieve(url=url1, filename=file_name1)
txt1 = re.split(pattern=r'\.', string=file_name1)[0] + ".txt"

with gzip.open(file_name1, 'rb') as f_in:
    with open(txt1, 'wb') as f_out:
        shutil.copyfileobj(f_in, f_out)