Python 打包:用户指定的文件路径

Python Packaging: user specified file path

我正在写一个 python 包,它依赖于大量的大数据文件。这些文件 包含在软件包中。相反,用户需要将这些文件放在磁盘上(使用任意路径)。让我的包知道这些文件的位置的最佳方法是什么?

我一直在阅读有关 setup.pysetup.cfg 的内容,但我仍然不确定如何阅读。在我看来,setup.cfg 中的用户可编辑选项将是一个不错的选择,但我不知道是否可以,是否可以完成,或者如果可以的话我会怎么做。 ..

我确实看到了这个几乎相同的问题,Python Packaging: Ask user for variable values when (pip) installing,它侧重于 pip 期间的用户输入(评论中不鼓励这样做)。 如果这实际上是一个很好的解决方案,我也很想知道如何做到这一点。

在我自己开发包的过程中,我使用了模块常量,如

DEFAULT_PATH_FILE1 = "my/path/to/file1.csv"
DEFAULT_PATH_FILE2 = "my/path/to/file2.csv"

等和使用这些常量初始化的属性。这似乎根本不适合分发。

这听起来像是运行时配置。这是 setup.py 业务的 none,它与 安装 您的程序包有关。

对于应用程序配置,通常通过命令行参数、环境变量或配置文件指定此资源位置。如果用户未指定任何配置,您通常会希望对一些合理的默认路径进行硬编码,或者在资源不存在/未找到的情况下引发异常。

环境变量示例:

import os

DEFAULT_PATH_FILE1 = "/default/path/to/file1.csv"
PATH_FILE1 = os.environ.get("PATH_FILE1", DEFAULT_PATH_FILE1)

您想要的不是安装期间的一次性设置(这对于现代 .whl 安装也是不可能的),而是一种让客户在运行时随时配置您的库的方法。鉴于您不提供 cli,您可以使用环境变量作为提供该选项的选项,或者查找用户定义的配置文件。

这是一个简单的方法,使用 appdirs 找出应该在哪里找到配置文件。它在导入您的包时加载,并告诉客户如果配置文件不存在有多糟糕。通常是:

  • 写日志消息
  • 使用默认设置
  • 抛出某种异常
  • 以上的组合
from logging import getLogger
from pathlib import Path
from configparser import ConfigParser
# loads .ini format files easily, just to have an example to go with

import appdirs  # needs to be pip-installed

log = getLogger(__name__)
config = ConfigParser(interpolation=None)


# load config, substitute "my_package" with the actual name of your package
config_path = Path(appdirs.user_config_dir("my_package")) / "user.ini"
try:
    with open(config_path) as f:
        config.read_file(f, source="user")
except FileNotFoundError:
    # only do whatever makes sense
    log.info(f"User config expected at '{config_path}', but not found.")
    config.read_string("[pathes]\nfile_foo=foo\nfile_bar=bar")  # dubious
    raise ImportError(f"Can't use this module; create a config at '{config_path}'.")


class Foo:
    def __init__(self):
        with open(cfg["pathes"]["file_foo"]) as f:
            self.data = f.read()