2011-03-18 50 views
18

對於python來說相當新,我最近才發現通過在文件的頂部放置一個__main__.py文件來直接執行.zip文件的能力。這適用於python代碼,但是我可以捆綁其他類型的文件並使用我的腳本訪問它們嗎?如果是這樣,怎麼樣?python:可執行zip文件包含數據文件嗎?

我的最終目標是將一些圖像文件和python代碼捆綁在一個.zip文件中,然後就可以在應用程序中使用這些圖像,而無需將它們提取到磁盤。我還想捆綁版權聲明,發行說明等,以便整個應用程序及其數據文件都可以在一個zip文件中執行,無需將其解壓到某個位置即可執行。

回答

15

你可以使用pkg_resources功能來訪問文件:

# __main__.py 
import pkg_resources 
from PIL import Image 

print pkg_resources.resource_string(__name__, 'README.txt') 

im = Image.open(pkg_resources.resource_stream('app', 'im.png')) 
im.rotate(45).show() 

如果zip文件包含:

. 
|-- app 
| |-- im.png 
| `-- __init__.py 
|-- README.txt 
`-- __main__.py

爲了壓縮文件的可執行文件,運行:

$ echo '#!/usr/bin/env python' | cat - zipfile > program-name 
$ chmod +x program-name 

爲了測試它:

$ cp program-name /another-dir/ 
$ cd /another-dir && ./program-name 
+1

這隻適用於安裝了setuptools的pkg_resources模塊 – 2011-03-22 19:53:45

+1

[Python中的''zipapp'模塊] (https://docs.python.org/3/library/zipapp.html),可以自動創建檔案。 – jfs 2016-01-18 05:57:29

5

至少在我的Linux機器上,進程沒有打開文件句柄或映射的內存到它自己的zip文件,所以想必沒有辦法「神奇」地訪問它。

但是,創建自己的訪問並不困難。創建一個__main__.py像這樣:

import os, zipfile 

me = zipfile.ZipFile(os.path.dirname(__file__), 'r') 
f = me.open('other.txt') 
print f.read() 
f.close() 
me.close() 

編輯:有點簡潔,那。爲了完整:

$ echo "Hello ZIP" > other.txt 
$ zip testo.zip __main__.py other.txt 
$ python testo.zip 
Hello ZIP 
+0

它永遠不會發生在我重新打開當前正在執行的zip文件。涼。不幸的是,當我在OSX上運行我的腳本時,'__file__'是'None'。我認爲這是朝正確方向邁出的一步。 – 2011-03-18 18:21:59

+0

@Bryan Oakley:如果zipfile中的第一行是'#!/ usr/bin/env python'或類似文件,'sys.argv [0]'包含zipfile路徑。 – jfs 2011-03-18 20:20:36

5

簡單地使用pkgutil.get_data()作爲this answer

+0

這隻適用於將文件放入包中的情況,這意味着它不適用於zip文件根目錄下的README.txt或COPYRIGHT.txt文件。這不是關鍵問題,但我希望能夠將某些文件放在zip文件層次結構頂部的__main__.py旁邊。 – 2011-03-18 19:15:22

+0

通常你的主模塊可以通過導入'__main__'訪問,你可以參考它 – 2011-03-18 19:44:53

+0

Combell:我希望這是真的。至少在我的測試中。OSX和Python 2.6上的zip文件,__main__未定義。 – 2011-03-18 19:49:54

0

pkgutil.get_data(package, resource)建議採取包和資源的名稱。這意味着你必須將你的數據文件放在zip文件中的一個包中。

因此,例如,包含一個zip文件:

__main__.py 
zippeddata/__init__.py 
zippeddata/data.txt 

__init__.py文件可以爲空或只是一個評論,但你需要一個做zippeddata可導入。

然後在__main__.py您只要致電:

data = pkgutil.get_data('zippeddata', 'data.txt')