我正在尝试用结构中的一些数据来打包应用程序。该应用程序将对DDBB执行一系列查询,并最终生成一个脚本,该脚本将启动到批处理系统(SLURM(。该脚本将基于模板(我正在访问的资源的一部分(,并将引用一些助手脚本,这些脚本也将被打包为资源:
./
src/
package/
__init__.py
code.py
templates/
job.tmplt
helpers/
helper1.sh
helper2.sh
根据Python手册,应该访问如下资源:
from importlib.resources import as_file, files
template_in = files("package.templates") / "job.tmplt"
helper_base = as_file(files("package.helpers"))
cmd = Path("job.cmd")
with template_in.open("r") as tmplt_in, cmd.open("w") as job_out:
print(f"{helper_base.resolve()}/helper1.sh", file=job_out)
但这并不奏效。helper_base
不是真正的Path
对象,并且无法返回真正的路径名。我知道这是因为它可能在zip文件中,importlib.resources
方便我访问该文件(如果需要,还可以进行后期清理(。但我的用例不同:我只需要一个对文件的引用,该引用在脚本完成后很长一段时间内都是有效的(因为它将被批处理系统使用(。
是否有任何方法可以获得未封装在任何容器(如zip(中的资源的干净路径,以便在脚本完成后访问该资源?
正如@sinoroc所评论的,没有办法做到这一点。最好的方法是在;设置/安装";将数据从包复制到包外磁盘中的目的地的步骤(通常为$XDG_data_HOME/$APPLICATION(。
我使用的代码是:
from pathlib import Path
from importlib.resources import files
from platformdirs import user_data_path
def _get_data_dir(application: str) -> Path:
data_dir = user_data_path(application)
if not data_dir.exists():
data_dir.mkdir(parents=True)
return data_dir
def _populate_data_dir(data_dir: Path, package: str, force: bool = False) -> None:
for file in files(package).iterdir():
destination = data_dir / file.name
if force or not destination.exists():
with destination.open("w", encoding="UTF-8") as f_destination:
f_destination.write(file.read_text())
_populate_data_dir(_get_data_dir("myapp"), "my_package")
这段代码假设包目录中没有文件夹(否则,您将不得不不同地处理它们(,并且要复制的文件很小(因为它们完全读取到内存中(。