简体   繁体   English

configparser从zip加载配置文件

[英]configparser loading config files from zip

I am creating a program that loads and runs python scripts from a compressed file. 我正在创建一个程序,该程序从压缩文件加载并运行python脚本。 Along with those python scripts, I have a config file that I previously used configparser to load info from in an uncompressed version of the program. 除了这些python脚本外,我还有一个配置文件,我以前使用configparser从该程序的未压缩版本中加载信息。

Is it possible to directly read config files in zip files directly with configparser? 是否可以直接使用configparser直接读取zip文件中的配置文件? or do I have to unzip it into a temp folder and load it from there? 还是我必须将其解压缩到一个临时文件夹中并从那里加载它?

I have tried directly giving the path: 我尝试直接给出路径:

>>> sysconf = configparser.ConfigParser()
>>> sysconf.read_file("compressed.zip/config_data.conf")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/configparser.py", line 691, in read_file
    self._read(f, source)
  File "/usr/local/lib/python3.4/configparser.py", line 1058, in _read
    raise MissingSectionHeaderError(fpname, lineno, line)
configparser.MissingSectionHeaderError: File contains no section headers.
file: '<???>', line: 1

Didn't work. 没用 no surprises there. 没有惊喜。

Then I tried using zipfile 然后我尝试使用zipfile

 >>> zf = zipfile.ZipFile("compressed.zip")
 >>> data = zf.read("config_data.conf")
 >>> sysconf = configparser.ConfigParser()
 >>> sysconf.read_file(data)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/configparser.py", line 691, in read_file
    self._read(f, source)
  File "/usr/local/lib/python3.4/configparser.py", line 1009, in _read
    if line.strip().startswith(prefix):
AttributeError: 'int' object has no attribute 'strip'

and found that it didn't work either. 并发现它也不起作用。

so I've resorted to creating a temp folder, uncompressing to it, and reading the conf file there. 因此,我不得不创建一个临时文件夹,将其解压缩,然后在其中读取conf文件。 I would really like to avoid this if possible as the conf files are the only limiting factor. 我真的想避免这种情况,因为conf文件是唯一的限制因素。 I can (and am) loading the python modules from the zip file just fine at this point. 此时,我可以(也可以)从zip文件加载python模块。

I can get the raw text of the file if there's a way to pass that directly to configparser, but searching the docs I came up empty handed. 如果有一种方法可以将其直接传递给configparser,则可以获取文件的原始文本,但是我空手搜索我找到的文档。

Update: I tried using stringIO as a file object, and it seems to work somewhat. 更新:我尝试将stringIO用作文件对象,但似乎有些正常。 configparser doesn't reject it, but it doesn't like it either. configparser不会拒绝它,但是也不喜欢它。

>>> zf = zipfile.ZipFile("compressed.zip")
>>> data = zf.read(config_data.conf)
>>> confdata = io.StringIO(str(data))
>>> sysconf = configparser.ConfigParser()
>>> sysconf.readfp(confdata)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/configparser.py", line 736, in readfp
    self.read_file(fp, source=filename)
  File "/usr/local/lib/python3.4/configparser.py", line 691, in read_file
    self._read(f, source)
  File "/usr/local/lib/python3.4/configparser.py", line 1058, in _read
    raise MissingSectionHeaderError(fpname, lineno, line)
configparser.MissingSectionHeaderError: File contains no section headers.
file: '<???>', line: 1
(continues to spit out the entire contents of the file)

If I use read_file instead, it doesn't error out, but doesn't load anything either. 如果我改用read_file,它不会出错,但也不会加载任何东西。

>>> zf = zipfile.ZipFile("compressed.zip")
>>> data = zf.read(config_data.conf)
>>> confdata = io.StringIO(str(data))
>>> sysconf = configparser.ConfigParser()
>>> sysconf.read_file(confdata)
>>> sysconf.items("General") #(this is the main section in the file)
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/configparser.py", line 824, in items
    d.update(self._sections[section])
KeyError: 'General'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/configparser.py", line 827, in items
    raise NoSectionError(section)
configparser.NoSectionError: No section: 'General'

can get the raw text of the file if there's a way to pass that directly to configparser 如果有一种方法可以直接将其传递给configparser,则可以获取文件的原始文本

Try configparser.ConfigParser.read_string 尝试configparser.ConfigParser.read_string

When coupled with an appropriate ZIP file, this code works for me: 结合适当的ZIP文件后,此代码对我有用:

import zipfile
import configparser

zf = zipfile.ZipFile("compressed.zip")
zf_config = zf.open("config_data.conf", "rU")
zf_config_data = zf_config.read().decode('ascii')

config = configparser.ConfigParser()
config.read_string(zf_config_data)
assert config['today']['lunch']=='cheeseburger'

Upon reflection, the following might be more appropriate: 经过反思,以下内容可能更合适:

import zipfile
import configparser
import io

zf = zipfile.ZipFile("compressed.zip")
zf_config = zf.open("config_data.conf", "rU")
zf_config = io.TextIOWrapper(zf_config)

config = configparser.ConfigParser()
config.read_file(zf_config)
assert config['today']['lunch']=='cheeseburger'

ZipFile not only supports read but also open , which returns a file-like object. ZipFile不仅支持read ,还支持open ,它返回一个类似文件的对象。 So, you could do something like this: 因此,您可以执行以下操作:

zf = zipfile.ZipFile("compressed.zip")
config_file = zf.open("config_data.conf")
sysconfig = configparser.ConfigParser()
sysconfig.readfp(config_file)

As written in comments, @matthewatabet answer won't work with Python 3.4 (and newer vesions). 正如评论中所写,@ matthewatabet答案不适用于Python 3.4(和较新版本)。 It's because ZipFile.open now returns a "bytes-like" object and not a "file-like" object anymore. 这是因为ZipFile.open现在返回的是“字节状”对象,而不是“文件状”对象。 You can use: 您可以使用:

codecs.getreader("utf-8")(config_file)

To convert the config_file bytes-like object into a file-like object using the UTF-8 encoding. 使用UTF-8编码将config_file类似字节的对象转换为类似文件的对象。 The code is now: 现在的代码是:

import zipfile, configparser, codecs

with zipfile.ZipFile("compressed.zip") as zf:
    config_file = zf.open("config_data.conf")
    sysconfig = configparser.ConfigParser()
    sysconfig.read_file(codecs.getreader("utf-8")(config_file))

That seems more satisfactory than creating a string , but I don't know if it's more efficient... 这似乎比创建string更令人满意,但我不知道它是否更有效...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM