首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何访问zipapp中的文件

如何访问zipapp中的文件
EN

Stack Overflow用户
提问于 2019-11-13 11:32:02
回答 2查看 927关注 0票数 6

我使用以下命令构建了一个简单的Python 齐帕普

代码语言:javascript
复制
python -m pkg/ -c -o test -p '/usr/bin/python3' -m 'test:main' zipapp

我想从脚本中访问二进制文件。

代码语言:javascript
复制
$ cat pkg/test.py 
def main():
    with open('test.bin', 'rb') as f:
        print(f.name)

目录结构

代码语言:javascript
复制
$ tree pkg/
pkg/
├── test.bin
└── test.py

0 directories, 2 files

但是看起来脚本引用的是当前目录中的一个文件:

代码语言:javascript
复制
$ ./test 
Traceback (most recent call last):
  File "/usr/lib64/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "./test/__main__.py", line 3, in <module>
  File "./test/test.py", line 2, in main
FileNotFoundError: [Errno 2] No such file or directory: 'test.bin'

这是一个相当大的二进制文件,所以我想避免创建一个变量。有办法从脚本本身访问这个文件吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-13 13:28:50

好的,看起来我可以在脚本本身中打开zip文件:

代码语言:javascript
复制
import zipfile

def main():
    with zipfile.ZipFile(os.path.dirname(__file__)) as z:
        print(z.namelist())
        with z.open('test.bin') as f:
            print(f.name)
票数 3
EN

Stack Overflow用户

发布于 2021-05-11 19:36:11

虽然被接受的答案有效,但它也有一些缺陷。主要原因是,该应用程序现在只能作为zipapp运行。相反,可以使用importlib.resources模块同时支持两种模式:

代码语言:javascript
复制
import importlib.resources

def main():
    # if you use multiple packages you can replace '__package__'
    # with an explicit module specifier like 'foobar.templates'
    print(importlib.resources.read_text(__package__, "data.txt"), end="")

if __name__ == "__main__":
    # this is used to support calling with 'python3 -m ...'
    main()
代码语言:javascript
复制
$ tree
.
└── myapp
    └── mypackage
        ├── cli.py
        ├── data.txt (contains "Hello World")
        └── __init__.py

2 directories, 3 files
$ (cd myapp && python3 -m mypackage.cli) # still callable in unzipped mode
Hello World
$ python3 -m zipapp --python "/usr/bin/env python3" --main "mypackage.cli:main" myapp      
$ ./myapp.pyz
Hello World

您只需小心将数据放入适当的包中即可。也就是说,在包目录中需要一个__init__.py文件,并且包本身必须是传递给python3 -m zipapp的目录的一个子目录。否则,importlib.resources将不会识别包本身,并且无法导入任何数据。

代码语言:javascript
复制
$ unzip -l myapp.pyz
Archive:  myapp.pyz
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2021-05-11 21:26   mypackage/
      282  2021-05-11 21:25   mypackage/cli.py
        0  2021-05-11 19:39   mypackage/__init__.py
        0  2021-05-11 21:26   mypackage/__pycache__/
       12  2021-05-11 19:39   mypackage/data.txt
      427  2021-05-11 21:26   mypackage/__pycache__/cli.cpython-38.pyc
      168  2021-05-11 21:26   mypackage/__pycache__/__init__.cpython-38.pyc
       66  2021-05-11 21:27   __main__.py
---------                     -------
      955                     8 files
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58836162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档