Abh*_*nia 6 python import config configparser python-2.7
我正在编写我想上传到 PyPI 的第一个 python 包。我根据这篇博文构建了我的代码。
我想将用户设置存储在 config.ini 文件中。在同一包中的单独 python 模块中读取一次(每次包运行时),并将用户设置保存在该模块的全局变量中。稍后导入其他模块中的那些。
为了重现错误,我刚刚在博客文章中描述的模板中编辑了几行代码。(请参考它,因为在此处重新创建整个内容需要太多的输入。)
唯一的区别是我stuff.py
从这样的配置文件中读取:
from ConfigParser import SafeConfigParser
config = SafeConfigParser()
config.read('config.ini')
TEST_KEY = config.get('main', 'test_key')
Run Code Online (Sandbox Code Playgroud)
以下是config.ini
(放置在与 相同的目录中stuff.py
)的内容:
[main]
test_key=value
Run Code Online (Sandbox Code Playgroud)
而我bootstrap.py
刚刚导入并打印TEST_KEY
from .stuff import TEST_KEY
def main():
print(TEST_KEY)
Run Code Online (Sandbox Code Playgroud)
但是在执行包时,导入失败给出这个错误
Traceback (most recent call last):
File "D:\Coding\bootstrap\bootstrap-runner.py", line 8, in <module>
from bootstrap.bootstrap import main
File "D:\Coding\bootstrap\bootstrap\bootstrap.py", line 11, in <module>
from .stuff import TEST_KEY
File "D:\Coding\bootstrap\bootstrap\stuff.py", line 14, in <module>
TEST_KEY = config.get('main', 'test_key')
File "C:\Python27\Lib\ConfigParser.py", line 607, in get
raise NoSectionError(section)
ConfigParser.NoSectionError: No section: 'main'
Run Code Online (Sandbox Code Playgroud)
进口一直给ConfigParser.NoSectionError,但如果你建立/只运行stuff.py(我使用sublime3),该模块提供任何错误和打印TEST_KEY
给value
作为输出。
此外,当我只在目录中使用 3 个文件(config、stuff、main)并将 main 作为脚本执行时,这种导入方法确实有效。但我不得不像这样导入它
from stuff import TEST_KEY
Run Code Online (Sandbox Code Playgroud)
我只是使用该帖子中描述的显式相对导入,但对这些没有足够的了解。我猜这个错误是由于项目结构和导入造成的,因为stuff.py
作为独立脚本运行不会引发ConfigParser.NoSectionError
.
读取配置文件一次然后在其他模块中使用数据的其他方法也将非常有用。
这个问题有两个方面。首先是ConfigParser
. 何时ConfigParser
无法定位.ini
文件;由于某些烦人的原因,它永远不会给出一个IOError
或错误,表明它无法读取文件。
在我的情况下,ConfigParser.NoSectionError
当section
明确存在时,它会继续给予。当我发现ConfigParser.NoSectionError
错误时,它给出了一个ImportError
! 但它永远不会告诉您它根本无法读取文件。
其次是如何安全地读取包中包含的数据文件。我发现这样做的唯一方法是使用__file__
参数。config.ini
对于 Python27 和 Python3,您可以这样安全地阅读上述问题中的内容:
import os
try:
# >3.2
from configparser import ConfigParser
except ImportError:
# python27
# Refer to the older SafeConfigParser as ConfigParser
from ConfigParser import SafeConfigParser as ConfigParser
config = ConfigParser()
# get the path to config.ini
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.ini')
# check if the path is to a valid file
if not os.path.isfile(config_path):
raise BadConfigError # not a standard python exception
config.read(config_path)
TEST_KEY = config.get('main', 'test_key') # value
Run Code Online (Sandbox Code Playgroud)
这取决于config.ini
位于我们包裹内bootstrap
并预计随包裹一起发货的事实。
重要的是你如何获得config_path
:
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.ini')
Run Code Online (Sandbox Code Playgroud)
__file__
指的是当前script
正在执行的位置。在我的问题中,这意味着stuff.py
, 即bootstrap
文件夹内的位置,config.ini
.
上面的代码行意味着; 获取到的绝对路径stuff.py
;从那个获取路径到包含它的目录;并将其加入config.ini
(因为它在同一目录中)以提供config.ini
. 然后你可以继续阅读它并提出一个exception
以防万一。
即使您发布软件包pip
并且用户从那里安装它,这也将起作用。
作为奖励,并且稍微偏离问题,如果您要在包中pip
使用数据文件发布包,则必须setuptools
在构建sdist
和bdist
s时告诉将它们包含在包中。所以要包含config.ini
在上面的包中,将以下行添加到setup
类调用中setup.py
:
include_package_data = True,
package_data = {
# If any package contains *.ini files, include them
'': ['*.ini'],
},
Run Code Online (Sandbox Code Playgroud)
但在某些情况下它仍然可能不起作用,例如。建造轮子等。所以你也在你的MANIFEST.IN
文件中做同样的事情:
include LICENSE
include bootstrap/*.ini
Run Code Online (Sandbox Code Playgroud)
小智 3
abhimanyuPathania:问题在于config.ini
in的路径stuff.py
。更改config.read('config.ini')
为config.read('./bootstrap/config.ini')
在stuff.py
. 我尝试了解决方案。这个对我有用。
享受Python语言...
归档时间: |
|
查看次数: |
9321 次 |
最近记录: |