在 setup.py 应用程序中提供对模块相关文件的访问的公认做法

Accepted practice to provide access to a module-relative file in a setup.py application

(对不起,文字墙,但我想确保包括我的问题的所有相关细节)

我大致遵循概述的应用程序结构 here。我还有一个 logging.conf 文件,我希望我的应用程序在所有情况下都使用该文件:

结构大致是:

myapp/
├── build
├── dist
├── MANIFEST.in
├── myapp
│   ├── lib
│   │   ├── helpers.py
│   │   ├── __init__.py
│   │   └── startup.py
│   ├── logging.conf
│   ├── cmd
│   │   ├── cmd1.py
│   │   ├── cmd2.py
│   │   ├── cmd3.py
│   │   └── __init__.py
│   ├── __main__.py
│   ├── settings.py
│   └── tox.ini
├── README.md
├── requirements.txt
├── setup.cfg
├── setup.py
├── tests
└── venv

在我的一个模块 (lib/startup.py) 中,用于我所有的应用程序入口点 (__main__.pycmd1cmd2cmd3 , ...) 我正在(提前)加载记录器配置,

logging.config.fileConfig('logging.conf')

在我的 MANIFEST.in 中,安装了 logging.conf。执行 python setup.py install:

时,一切似乎都已正确安装在 virtualenv 中

并且可以通过所有提供的方式启动应用程序:

而且我也可以 运行 在我的开发环境中:

myapp/myapp $ python cmd/cmd1.py

但是,在开发环境中发现logging.conf没有问题(在cwd中),安装的模块找不到这个文件,执行失败:

$ python -m cmd1

Traceback (most recent call last):
  File "/usr/lib/python3.4/runpy.py", line 170, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.4/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "myapp/venv/lib/python3.4/site-packages/myapp-0.5.0-py3.4.egg/myapp/__main__.py", line 5, in <module>
    from myapp.cmd.cmd1 import main
  File "myapp/venv/lib/python3.4/site-packages/myapp-0.5.0-py3.4.egg/myapp/cmd/cmd1.py", line 2, in <module>
    from myapp.lib.startup import start_trading
  File "myapp/venv/lib/python3.4/site-packages/myapp-0.5.0-py3.4.egg/myapp/lib/startup.py", line 10, in <module>
    logging.config.fileConfig('logging.conf')
  File "/usr/lib/python3.4/logging/config.py", line 76, in fileConfig
    formatters = _create_formatters(cp)
  File "/usr/lib/python3.4/logging/config.py", line 109, in _create_formatters
    flist = cp["formatters"]["keys"]
  File "/usr/lib/python3.4/configparser.py", line 937, in __getitem__
    raise KeyError(key)
KeyError: 'formatters'

如何确保我安装的应用程序能够找到模块相关文件?我不能在我的代码中使用绝对路径,因为我不知道安装路径......是否有推荐的最佳实践?

免责声明。我不确定这种方法是否被接受。但这绝对是最简单的。

您可以使用 __file__ global variable to get relative path to the currently running *.py file. Having it you can calculate path to the resource file. Take a look at this answer 了解更多详情。

根据您的示例,您可以像这样计算 startup.pylogging.conf 的路径:

import os

# path to the logging.conf
config_path = os.path.join(os.path.dirname(__file__), '../logging.conf')
print(config_path)

# normalized path to the logging.conf (optionally) 
norm_config_path = os.path.normpath(config_path)
print(norm_config_path)