从 python egg 访问文件
Access a file from a python egg
您好,我正在使用 python 包装。我有 3 个 non-code
个文件,即 ['synonyms.csv', 'acronyms.csv', 'words.txt']
。
- 这些文件存在于文件夹结构中
Wordproject/WordProject/Repository/DataBank/
- 我在路径
Wordproject/WordProject/Repository/
有一个 RepositoryReader
class
- 我写了一段代码,可以提取
RepositoryReader
的当前位置,然后查找名为 DataBank
的 subdirectory
并在那里查找 3 个文件。
问题是当我从代码中创建一个 egg
,然后 运行 它,
我的代码给出错误:
Could not find the file at X:. Projects\Python\Wordproject\venv\lib\site-packages\Wordproject-1.0-py3.6.egg\Wordproject\Repository\DataBank\synonyms.csv
如果路径是鸡蛋,则无法从路径中获取文件或读取文件。有什么办法吗?这些文件必须在 egg
.
中
egg
文件只是重命名为 .zip 文件。
您可以使用zipfile
库打开egg并提取或读取您需要的文件。
import zipfile
zip = zipfile.ZipFile('/path/to/file.egg', 'r')
# open file from within the egg
f = zip.open('synonyms.csv', 'r')
txt = f.read()
您可以在这里尝试做两种不同的事情:
- 将数据文件视为包的一部分,就像 Python 模块一样,并在运行时访问它们,就像您的包是普通目录树一样,即使它不是。
- 在
pip install
时获取安装在其他地方的数据文件,到您可以正常访问的位置。
两者在the section on data files in the PyPA/setuptools
docs. I think you want the first one here, which is covered in the subsection on Accessing Data Files at Runtime中都有解释:
Typically, existing programs manipulate a package’s __file__
attribute in order to find the location of data files. However, this manipulation isn’t compatible with PEP 302-based import hooks, including importing from zip files and Python Eggs. It is strongly recommended that, if you are using data files, you should use the ResourceManager API of pkg_resources
to access them. The pkg_resources
module is distributed as part of setuptools
, so if you’re using setuptools
to distribute your package, there is no reason not to use its resource management API. See also Accessing Package Resources for a quick example of converting code that uses __file__
to use pkg_resources
instead.
跟随 link,您会发现一些看起来像一些笨拙的旧 PEAK 文档的内容,但这只是因为它们确实是笨拙的旧 PEAK 文档。有一个 version buried inside the setuptools
docs,一旦您设法找到它,您可能会发现它更易于阅读和导航。
正如它所说,您 可以 try
使用 get_data
(这将在 egg/zip 内工作)然后回退到访问一个文件(当来自源 运行 时可以工作),但你最好使用 pkg_resources
中的包装器。基本上,如果您的代码是这样做的:
path = os.path.join(__file__, 'Wordproject/WordProject/Repository/DataBank/', datathingy)
with open(path) as f:
for line in f:
do_stuff(line)
…你会把它改成这样:
path = 'Wordproject/WordProject/Repository/DataBank/' + datathingy
f = pkg_resources.resource_stream(__name__, path)
for line in f:
do_stuff(line.decode())
请注意 resource_stream
文件始终以二进制模式打开。因此,如果你想将它们作为文本阅读,你需要在它们周围包裹一个 TextIOWrapper
,或者解码每一行。
基于documentation,我们可以通过多种方式读取文件内容。
方案一:直接将文件内容读入内存
没有在本地提取文件。
import zipfile, tempfile
tfile = tempfile.NamedTemporaryFile()
with zipfile.ZipFile('/path/to/egg.egg') as myzip:
with myzip.open('relative/path/to/file.txt') as myfile:
tfile.write(myfile.read())
# .. do something with temporary file
tfile.close()
现在 tfile
是您的本地临时文件句柄。它的名称是 tfile.name
并且所有文件操作(例如 open(tfile)
等)都照常进行。 tfile.close()
必须在最后调用以关闭句柄。
文件内容可以被 myfile.read()
本身读取,但是一旦退出上下文,我们就会丢失 myfile 句柄。因此,如果需要为其他操作传递文件内容,则会将其复制到临时文件中。
方案二:在本地提取egg成员
zipfile 提供了一个 API 用于提取特定成员
import zipfile
x = zipfile.ZipFile('/path/to/egg.egg')
x.extractall(path='temp/dest/folder', members=['path/to/file.txt'])
解决方案 3:提取整个鸡蛋
另一种解决方案是将egg解压到临时文件夹中,然后读取文件。 Egg 可以在命令行中提取如下
python -m zipfile -e path/to/my.egg ./temp_destination
如果您使用的是 Python 3.7 或更高版本,我建议您使用 importlib_resources。从他们的文档 https://importlib-resources.readthedocs.io/en/latest/using.html 中,这里有一个将 YAML 文件放入模块的示例:
from importlib_resources import files, as_file
yaml_path = files('my-module').joinpath('openapi.yml')
with as_file(yaml_path) as yaml:
conn_app.add_api(yaml)
如果通过 pip3 install .
将模块安装在目录中,并且 如果通过 python3 setup.py install
[=] 作为 egg (zip) 文件安装,则此方法有效14=]
您好,我正在使用 python 包装。我有 3 个 non-code
个文件,即 ['synonyms.csv', 'acronyms.csv', 'words.txt']
。
- 这些文件存在于文件夹结构中
Wordproject/WordProject/Repository/DataBank/
- 我在路径
Wordproject/WordProject/Repository/
有一个 - 我写了一段代码,可以提取
RepositoryReader
的当前位置,然后查找名为DataBank
的subdirectory
并在那里查找 3 个文件。
RepositoryReader
class
问题是当我从代码中创建一个 egg
,然后 运行 它,
我的代码给出错误:
Could not find the file at X:. Projects\Python\Wordproject\venv\lib\site-packages\Wordproject-1.0-py3.6.egg\Wordproject\Repository\DataBank\synonyms.csv
如果路径是鸡蛋,则无法从路径中获取文件或读取文件。有什么办法吗?这些文件必须在 egg
.
egg
文件只是重命名为 .zip 文件。
您可以使用zipfile
库打开egg并提取或读取您需要的文件。
import zipfile
zip = zipfile.ZipFile('/path/to/file.egg', 'r')
# open file from within the egg
f = zip.open('synonyms.csv', 'r')
txt = f.read()
您可以在这里尝试做两种不同的事情:
- 将数据文件视为包的一部分,就像 Python 模块一样,并在运行时访问它们,就像您的包是普通目录树一样,即使它不是。
- 在
pip install
时获取安装在其他地方的数据文件,到您可以正常访问的位置。
两者在the section on data files in the PyPA/setuptools
docs. I think you want the first one here, which is covered in the subsection on Accessing Data Files at Runtime中都有解释:
Typically, existing programs manipulate a package’s
__file__
attribute in order to find the location of data files. However, this manipulation isn’t compatible with PEP 302-based import hooks, including importing from zip files and Python Eggs. It is strongly recommended that, if you are using data files, you should use the ResourceManager API ofpkg_resources
to access them. Thepkg_resources
module is distributed as part ofsetuptools
, so if you’re usingsetuptools
to distribute your package, there is no reason not to use its resource management API. See also Accessing Package Resources for a quick example of converting code that uses__file__
to usepkg_resources
instead.
跟随 link,您会发现一些看起来像一些笨拙的旧 PEAK 文档的内容,但这只是因为它们确实是笨拙的旧 PEAK 文档。有一个 version buried inside the setuptools
docs,一旦您设法找到它,您可能会发现它更易于阅读和导航。
正如它所说,您 可以 try
使用 get_data
(这将在 egg/zip 内工作)然后回退到访问一个文件(当来自源 运行 时可以工作),但你最好使用 pkg_resources
中的包装器。基本上,如果您的代码是这样做的:
path = os.path.join(__file__, 'Wordproject/WordProject/Repository/DataBank/', datathingy)
with open(path) as f:
for line in f:
do_stuff(line)
…你会把它改成这样:
path = 'Wordproject/WordProject/Repository/DataBank/' + datathingy
f = pkg_resources.resource_stream(__name__, path)
for line in f:
do_stuff(line.decode())
请注意 resource_stream
文件始终以二进制模式打开。因此,如果你想将它们作为文本阅读,你需要在它们周围包裹一个 TextIOWrapper
,或者解码每一行。
基于documentation,我们可以通过多种方式读取文件内容。
方案一:直接将文件内容读入内存
没有在本地提取文件。
import zipfile, tempfile
tfile = tempfile.NamedTemporaryFile()
with zipfile.ZipFile('/path/to/egg.egg') as myzip:
with myzip.open('relative/path/to/file.txt') as myfile:
tfile.write(myfile.read())
# .. do something with temporary file
tfile.close()
现在 tfile
是您的本地临时文件句柄。它的名称是 tfile.name
并且所有文件操作(例如 open(tfile)
等)都照常进行。 tfile.close()
必须在最后调用以关闭句柄。
文件内容可以被 myfile.read()
本身读取,但是一旦退出上下文,我们就会丢失 myfile 句柄。因此,如果需要为其他操作传递文件内容,则会将其复制到临时文件中。
方案二:在本地提取egg成员
zipfile 提供了一个 API 用于提取特定成员
import zipfile
x = zipfile.ZipFile('/path/to/egg.egg')
x.extractall(path='temp/dest/folder', members=['path/to/file.txt'])
解决方案 3:提取整个鸡蛋
另一种解决方案是将egg解压到临时文件夹中,然后读取文件。 Egg 可以在命令行中提取如下
python -m zipfile -e path/to/my.egg ./temp_destination
如果您使用的是 Python 3.7 或更高版本,我建议您使用 importlib_resources。从他们的文档 https://importlib-resources.readthedocs.io/en/latest/using.html 中,这里有一个将 YAML 文件放入模块的示例:
from importlib_resources import files, as_file
yaml_path = files('my-module').joinpath('openapi.yml')
with as_file(yaml_path) as yaml:
conn_app.add_api(yaml)
如果通过 pip3 install .
将模块安装在目录中,并且 如果通过 python3 setup.py install
[=] 作为 egg (zip) 文件安装,则此方法有效14=]