Python setuptools:将配置文件分发到 OS 个特定目录
Python setuptools: Distribute configuration files to OS specific directories
我在使用 Python setuptools 时遇到了先有鸡还是先有蛋的问题。
我想要实现的是将配置文件与我的 pip 包一起分发(这本身完全可以使用 setup.py
中的 data_files
参数)到特定的 OS用户配置文件的常见位置(例如 Linux 上的 ~/.config
)。
我发现 OS "specificity" 可以使用 appdirs
[1] PyPi 包解决。还有我的问题 - appdirs
在安装我自己的包时不能保证安装,因为它是我的包的依赖项,因此在它之后安装(承诺鸡或鸡蛋 :))
我的 setup.py
包含这样的内容:
from setuptools import setup
from appdirs import AppDirs
...
setup(
...
data_files=[
(AppDirs(name, author).user_config_dir, ['config/myconfig'])
],
...
)
这可以在不编写我自己的 setuptools 版本的情况下解决吗(暗示 ;))?
正如我在评论中提到的,我建议随包一起分发文件的通用副本,然后在运行时将其复制到用户的配置目录(如果不存在)。
这应该不是很难,涉及:
使用 setuptools
的 package_data
(而不是 data_files
)。这会将文件放置在运行时可使用 pkg_resources
访问的位置,在特定 OS
的 "correct" 位置
程序运行时,使用appdirs
查找用户特定的本地安装文件。
如果不存在,用pkg_resources
找到文件复制到appdirs
提供的位置
虽然我还没有这样做,但由于 pkg_resources
的工作方式,这个过程应该适用于多个 OSes 和环境,并且作为奖励,在开发过程中也是如此。
示例setup.py
在 setup.py 中,您应该确保使用 package_data
:
为您的包包含数据文件
setup(
# ...
data_files={
"my_package": [ "my_package.conf.dist"
}
# ...
)
示例应用程序代码:
import os.path
import pkg_resources
import appdirs
def main():
"""Your app's main function"""
config = get_config()
# ...
# ...
def get_config():
"""Read configuration file and return its contents
"""
cfg_dir = appdirs.user_config_dir('MyApplication')
cfg_file = os.path.join(cfg_dir, 'my_application.conf')
if not os.path.isfile(cfg_file):
create_user_config(cfg_file)
with open(cfg_file) as f:
data = f.read()
# ... probably parse the file contents here ...
return data
def create_user_config(cfg_file):
"""Create the user's config file
Note: you can replace the copying of file contents using shutil.copyfile
"""
source = pkg_resources.resource_stream(__name__, 'my_package.conf.dist')
with open(cfg_file, 'w') as dest:
dest.writelines(source)
我希望这能澄清 pkg_resources
和 package_data
的用法。
我在使用 Python setuptools 时遇到了先有鸡还是先有蛋的问题。
我想要实现的是将配置文件与我的 pip 包一起分发(这本身完全可以使用 setup.py
中的 data_files
参数)到特定的 OS用户配置文件的常见位置(例如 Linux 上的 ~/.config
)。
我发现 OS "specificity" 可以使用 appdirs
[1] PyPi 包解决。还有我的问题 - appdirs
在安装我自己的包时不能保证安装,因为它是我的包的依赖项,因此在它之后安装(承诺鸡或鸡蛋 :))
我的 setup.py
包含这样的内容:
from setuptools import setup
from appdirs import AppDirs
...
setup(
...
data_files=[
(AppDirs(name, author).user_config_dir, ['config/myconfig'])
],
...
)
这可以在不编写我自己的 setuptools 版本的情况下解决吗(暗示 ;))?
正如我在评论中提到的,我建议随包一起分发文件的通用副本,然后在运行时将其复制到用户的配置目录(如果不存在)。
这应该不是很难,涉及:
使用
setuptools
的package_data
(而不是data_files
)。这会将文件放置在运行时可使用pkg_resources
访问的位置,在特定 OS 的 "correct" 位置
程序运行时,使用
appdirs
查找用户特定的本地安装文件。如果不存在,用
pkg_resources
找到文件复制到appdirs
提供的位置
虽然我还没有这样做,但由于 pkg_resources
的工作方式,这个过程应该适用于多个 OSes 和环境,并且作为奖励,在开发过程中也是如此。
示例setup.py
在 setup.py 中,您应该确保使用 package_data
:
setup(
# ...
data_files={
"my_package": [ "my_package.conf.dist"
}
# ...
)
示例应用程序代码:
import os.path
import pkg_resources
import appdirs
def main():
"""Your app's main function"""
config = get_config()
# ...
# ...
def get_config():
"""Read configuration file and return its contents
"""
cfg_dir = appdirs.user_config_dir('MyApplication')
cfg_file = os.path.join(cfg_dir, 'my_application.conf')
if not os.path.isfile(cfg_file):
create_user_config(cfg_file)
with open(cfg_file) as f:
data = f.read()
# ... probably parse the file contents here ...
return data
def create_user_config(cfg_file):
"""Create the user's config file
Note: you can replace the copying of file contents using shutil.copyfile
"""
source = pkg_resources.resource_stream(__name__, 'my_package.conf.dist')
with open(cfg_file, 'w') as dest:
dest.writelines(source)
我希望这能澄清 pkg_resources
和 package_data
的用法。