Python ConfigParser - 带引号的值

23

在使用 ConfigParser 模块时,我想在 cfg 文件中使用包含多个单词的值。在这种情况下,对于我来说,将字符串用引号括起来似乎很简单(例如:example.cfg):

[GENERAL]
onekey = "value in some words"

我的问题是,当我像这样使用值时,Python也将引号附加到字符串中:

config = ConfigParser()
config.read(["example.cfg"])
print config.get('GENERAL', 'onekey')

我确信有内置功能可以仅打印出'value in some words'而不是'"value in some words"'。这可能吗?谢谢。

8个回答

16

我在configparser手册中没有看到相关内容,但您可以使用字符串的.strip方法来去除前导和尾随的双引号。

>>> s = '"hello world"'
>>> s
'"hello world"'
>>> s.strip('"')
'hello world'
>>> s2 = "foo"
>>> s2.strip('"')
'foo'

正如你所看到的,如果字符串不以指定的字符开头和结尾,.strip 不会修改该字符串。


5
请注意最后一句话需要更新。strip()函数如果字符串以指定字符串开头或结尾,则会修改该字符串。例如,'"bar'.strip("'")返回的是'bar'而不是bar - Jonny

11
import ConfigParser

class MyConfigParser(ConfigParser.RawConfigParser):
    def get(self, section, option):
        val = ConfigParser.RawConfigParser.get(self, section, option)
        return val.strip('"')

if __name__ == "__main__":
    #config = ConfigParser.RawConfigParser()
    config = MyConfigParser()

    config.read(["example.cfg"])
    print config.get('GENERAL', 'onekey') 

6

对不起,解决方案也很简单 - 我可以直接保留引号,因为在Python中它只需要等号右边的内容。


我刚遇到了同样的问题,这确实是解决方案。即,更改为[GENERAL] onekey = 一些单词中的值 - hzhang

5

这个问题已经很老了,但至少在2.6版本中,您不需要使用引号,因为空格是保留的。

from ConfigParser import RawConfigParser
from StringIO import StringIO

s = RawConfigParser()
s.readfp(StringIO('[t]\na= 1 2 3'))
s.get('t','a')
> '1 2 3'

然而,这并不适用于前导或尾随空格!如果您想保留它们,您需要将它们括在引号中并按建议进行操作。避免使用eval关键字,因为这会产生巨大的安全漏洞。


2
你可以编写以下配置读取函数,该函数以字典形式返回配置。"最初的回答"。

可以编写以下配置读取函数,该函数以字典形式返回配置。

def config_reader():
"""
Reads configuration from configuration file.
"""
configuration = ConfigParser.ConfigParser()
configuration.read(__file__.split('.')[0] + '.cfg')
config = {}
for section in configuration.sections():
    config[section] = {}
    for option in configuration.options(section):
        config[section][option] = (configuration.get(section, option)).strip('"').strip("'")
return config

1

我曾经也面临同样的问题。与其使用configparser对象,我更喜欢使用普通的字典。因此,首先我读取.ini文件,然后将configparser对象转换为字典,最后我从字符串值中删除引号(或撇号)。这是我的解决方案:

preferences.ini

[GENERAL]
onekey = "value in some words"

[SETTINGS]
resolution = '1024 x 768'

example.py

#!/usr/bin/env python3

from pprint import pprint
import preferences

prefs = preferences.Preferences("preferences.ini")
d = prefs.as_dict()
pprint(d)

preferences.py

import sys
import configparser
import json
from pprint import pprint

def remove_quotes(original):
    d = original.copy()
    for key, value in d.items():
        if isinstance(value, str):
            s = d[key]
            if s.startswith(('"', "'")):
                s = s[1:]
            if s.endswith(('"', "'")):
                s = s[:-1]
            d[key] = s
            # print(f"string found: {s}")
        if isinstance(value, dict):
            d[key] = remove_quotes(value)
    #
    return d

class Preferences:
    def __init__(self, preferences_ini):
        self.preferences_ini = preferences_ini

        self.config = configparser.ConfigParser()
        self.config.read(preferences_ini)

        self.d = self.to_dict(self.config._sections)

    def as_dict(self):
        return self.d

    def to_dict(self, config):
        """
        Nested OrderedDict to normal dict.
        Also, remove the annoying quotes (apostrophes) from around string values.
        """
        d = json.loads(json.dumps(config))
        d = remove_quotes(d)
        return d

d = remove_quotes(d)这行代码负责去除引号。注释/取消注释此行以查看差异。

输出:

$ ./example.py

{'GENERAL': {'onekey': 'value in some words'},
 'SETTINGS': {'resolution': '1024 x 768'}}

1

Davey,

正如你所说,你可以在字符串中省略引号。

对于我正在处理的一个项目,我希望能够将几乎任何Python字符串文字表示为某些配置选项的值,更重要的是,我希望能够将其中一些作为原始字符串文字进行处理。(我希望该配置能够处理诸如\n、\x1b等内容)。

在这种情况下,我使用了类似以下的代码:

def EvalStr(s, raw=False):
    r'''Attempt to evaluate a value as a Python string literal or
       return s unchanged.

       Attempts are made to wrap the value in one, then the 
       form of triple quote.  If the target contains both forms
       of triple quote, we'll just punt and return the original
       argument unmodified.

       Examples: (But note that this docstring is raw!)
       >>> EvalStr(r'this\t is a test\n and only a \x5c test')
       'this\t is a test\n and only a \\ test'

       >>> EvalStr(r'this\t is a test\n and only a \x5c test', 'raw')
       'this\\t is a test\\n and only a \\x5c test'
    '''

    results = s  ## Default returns s unchanged
    if raw:
       tmplate1 = 'r"""%s"""'
       tmplate2 = "r'''%s'''"
    else:
       tmplate1 = '"""%s"""'
       tmplate2 = "'''%s'''"

    try:
       results = eval(tmplate1 % s)
     except SyntaxError:
    try:
        results = eval(tmplate2 %s)
    except SyntaxError:
        pass
    return results

......我认为这将处理任何不包含三个单引号和三个双引号的字符串。

(那种情况远远超出了我的要求)。

这段代码在SO上有一个奇怪的地方; 语法高亮似乎被我的文档字符串是一个原始字符串所困惑。这对于使doctest对这个特定函数感到满意是必要的。


-3
在这种情况下,最简单的解决方案是使用 "eval()"。但是,您可能会担心安全问题。但是,您仍然可以通过以下方式实现:
def literal_eval(node_or_string):
    """
    Safely evaluate an expression node or a string containing a Python
    expression.  The string or node provided may only consist of the following
    Python literal structures: strings, numbers, tuples, lists, dicts,booleans,
    and None.
    """

举个例子:

import ast
config = ConfigParser()
config.read(["example.cfg"])
print ast.literal_eval(config.get('GENERAL', 'onekey'))
# value in some words

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接