Python 打包:用户指定的文件路径
Python Packaging: user specified file path
我正在写一个 python 包,它依赖于大量的大数据文件。这些文件 未 包含在软件包中。相反,用户需要将这些文件放在磁盘上(使用任意路径)。让我的包知道这些文件的位置的最佳方法是什么?
我一直在阅读有关 setup.py
和 setup.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()
我正在写一个 python 包,它依赖于大量的大数据文件。这些文件 未 包含在软件包中。相反,用户需要将这些文件放在磁盘上(使用任意路径)。让我的包知道这些文件的位置的最佳方法是什么?
我一直在阅读有关 setup.py
和 setup.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()