真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python如何解壓zip文件

今天小編給大家分享一下Python如何解壓zip文件的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、壽縣網(wǎng)絡(luò)推廣、重慶小程序開發(fā)公司、壽縣網(wǎng)絡(luò)營(yíng)銷、壽縣企業(yè)策劃、壽縣品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供壽縣建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:www.cdcxhl.com

原始函數(shù)

首先是下面這些模擬對(duì) zip 文件中文件實(shí)際操作的普通函數(shù):

def _count_file(fn): with open(fn, 'rb') as f:   return _count_file_object(f) def _count_file_object(f): # Note that this iterates on 'f'. # You *could* do 'return len(f.read())' # which would be faster but potentially memory # inefficient and unrealistic in terms of this # benchmark experiment. total = 0 for line in f:   total += len(line) return total

這里是可能最簡(jiǎn)單的另一個(gè)函數(shù):

def f1(fn, dest): with open(fn, 'rb') as f:   zf = zipfile.ZipFile(f)   zf.extractall(dest)  total = 0 for root, dirs, files in os.walk(dest):   for file_ in files:     fn = os.path.join(root, file_)     total += _count_file(fn) return total

如果我更仔細(xì)地分析一下,我將會(huì)發(fā)現(xiàn)這個(gè)函數(shù)花費(fèi)時(shí)間 40% 運(yùn)行 extractall,60% 的時(shí)間在遍歷各個(gè)文件并讀取其長(zhǎng)度。

第一步嘗試

我的***步嘗試是使用線程。先創(chuàng)建一個(gè) zipfile.ZipFile  的實(shí)例,展開其中的每個(gè)文件名,然后為每一個(gè)文件開始一個(gè)線程。每個(gè)線程都給它一個(gè)函數(shù)來做“實(shí)質(zhì)工作”(在這個(gè)基準(zhǔn)測(cè)試中,就是遍歷每個(gè)文件然后獲取它的名稱)。實(shí)際業(yè)務(wù)中的函數(shù)進(jìn)行的工作是復(fù)雜的  S3、redis 和 PostgreSQL 操作,但是在我的基準(zhǔn)測(cè)試中我只需要制作一個(gè)可以找出文件長(zhǎng)度的函數(shù)就好了。線程池函數(shù):

def f2(fn, dest):     def unzip_member(zf, member, dest):        zf.extract(member, dest)        fn = os.path.join(dest, member.filename)        return _count_file(fn)     with open(fn, 'rb') as f:        zf = zipfile.ZipFile(f)        futures = []        with concurrent.futures.ThreadPoolExecutor() as executor:            for member in zf.infolist():                futures.append(                    executor.submit(                        unzip_member,                        zf,                        member,                        dest,                    )                )            total = 0            for future in concurrent.futures.as_completed(futures):                total += future.result()    return total

結(jié)果:加速 ~10%

第二步嘗試

所以可能是 GIL(LCTT 譯注:Global Interpreter Lock,一種全局鎖,CPython  中的一個(gè)概念)阻礙了我。最自然的想法是嘗試使用多線程在多個(gè) CPU 上分配工作。但是這樣做有缺點(diǎn),那就是你不能傳遞一個(gè)非可 pickle  序列化的對(duì)象(LCTT 譯注:意為只有可 pickle 序列化的對(duì)象可以被傳遞),所以你只能發(fā)送文件名到之后的函數(shù)中:

def unzip_member_f3(zip_filepath, filename, dest):    with open(zip_filepath, 'rb') as f:        zf = zipfile.ZipFile(f)        zf.extract(filename, dest)    fn = os.path.join(dest, filename)    return _count_file(fn)   def f3(fn, dest):    with open(fn, 'rb') as f:        zf = zipfile.ZipFile(f)        futures = []        with concurrent.futures.ProcessPoolExecutor() as executor:            for member in zf.infolist():                futures.append(                    executor.submit(                        unzip_member_f3,                        fn,                        member.filename,                        dest,                    )                )            total = 0            for future in concurrent.futures.as_completed(futures):                total += future.result()    return total

結(jié)果: 加速 ~300%

這是作弊

使用處理器池的問題是這樣需要存儲(chǔ)在磁盤上的原始 .zip 文件。所以為了在我的 web 服務(wù)器上使用這個(gè)解決方案,我首先得要將內(nèi)存中的 zip 文件保存到磁盤,然后調(diào)用這個(gè)函數(shù)。這樣做的代價(jià)我不是很清楚但是應(yīng)該不低。

好吧,再翻翻看又沒有損失??赡?,解壓過程加速到足以彌補(bǔ)這樣做的損失了吧。

但是一定記??!這個(gè)優(yōu)化取決于使用所有可用的 CPU。如果一些其它的 CPU 需要執(zhí)行在 gunicorn 中的其它事務(wù)呢?這時(shí),這些其它進(jìn)程必須等待,直到有 CPU 可用。由于在這個(gè)服務(wù)器上有其他的事務(wù)正在進(jìn)行,我不是很確定我想要在進(jìn)程中接管所有其他 CPU。

結(jié)論

一步一步地做這個(gè)任務(wù)的這個(gè)過程感覺挺好的。你被限制在一個(gè) CPU 上但是表現(xiàn)仍然特別好。同樣地,一定要看看在f1 和 f2 兩段代碼之間的不同之處!利用 concurrent.futures 池類你可以獲取到允許使用的 CPU 的個(gè)數(shù),但是這樣做同樣給人感覺不是很好。如果你在虛擬環(huán)境中獲取的個(gè)數(shù)是錯(cuò)的呢?或者可用的個(gè)數(shù)太低以致無法從負(fù)載分配獲取好處并且現(xiàn)在你僅僅是為了移動(dòng)負(fù)載而支付營(yíng)運(yùn)開支呢?

我將會(huì)繼續(xù)使用 zipfile.ZipFile(file_buffer).extractall(temp_dir)。這個(gè)工作這樣做已經(jīng)足夠好了。

想試試手嗎?

我使用一個(gè) c5.4xlarge EC2 服務(wù)器來進(jìn)行我的基準(zhǔn)測(cè)試。文件可以從此處下載:

wget https://www.peterbe.com/unzip-in-parallel/hack.unzip-in-parallel.pywget https://www.peterbe.com/unzip-in-parallel/symbols-2017-11-27T14_15_30.zip

這里的 .zip 文件有 34MB。和在服務(wù)器上的相比已經(jīng)小了很多。

以上就是“Python如何解壓zip文件”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


當(dāng)前標(biāo)題:Python如何解壓zip文件
網(wǎng)頁鏈接:http://weahome.cn/article/pjpgsc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部