Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Zipap中访问文件_Python_Ziparchive - Fatal编程技术网

Python 如何在Zipap中访问文件

Python 如何在Zipap中访问文件,python,ziparchive,Python,Ziparchive,我使用以下命令构建了一个简单的Python: python -m pkg/ -c -o test -p '/usr/bin/python3' -m 'test:main' zipapp 我想从脚本中访问二进制文件 $ cat pkg/test.py def main(): with open('test.bin', 'rb') as f: print(f.name) 目录结构 $ tree pkg/ pkg/ ├── test.bin └── test.py 0

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

python -m pkg/ -c -o test -p '/usr/bin/python3' -m 'test:main' zipapp
我想从脚本中访问二进制文件

$ cat pkg/test.py 
def main():
    with open('test.bin', 'rb') as f:
        print(f.name)
目录结构

$ tree pkg/
pkg/
├── test.bin
└── test.py

0 directories, 2 files
但脚本似乎引用了当前目录中的文件:

$ ./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'
$/测试
回溯(最近一次呼叫最后一次):
文件“/usr/lib64/python3.7/runpy.py”,第193行,在“运行”模块中作为“主”
“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
文件“/usr/lib64/python3.7/runpy.py”,第85行,在运行代码中
exec(代码、运行\全局)
文件“/test/\uuuuuu main\uuuuuuuu.py”,第3行,在
文件“/test/test.py”,第2行,主
FileNotFoundError:[Errno 2]没有这样的文件或目录:“test.bin”

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

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

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)

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

导入导入lib.resources
def main():
#如果使用多个软件包,则可以替换“\uuuu-package\uuuuu”
#使用像“foobar.templates”这样的显式模块说明符
打印(importlib.resources.read_text(uuuu package_uuuu,“data.txt”),end=“”)
如果名称=“\uuuuu main\uuuuuuuu”:
#这是用来支持调用'python3-m…'
main()
您只需注意将数据放入适当的包中即可。 也就是说,在包目录中需要一个
\uuuu init\uuuu.py
文件 包本身必须是传递给python3-mzipapp的目录的子目录。 否则,
importlib.resources
将无法识别包本身,并且无法导入任何数据

$ 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
$ 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