如何使用configparser插入section-name

时间:2016-04-14 10:18:37

标签: python-3.x string-interpolation configparser

我正在使用[DEFAULT] compression=gzip [foo] output=/Backups/foo/ [pizza] output=/BigDisk/Backups/ [bar] output=/Backups/bar/ 来读取备份系统的配置。 其中一个选项(输出路径)经常包含section-name本身。

[DEFAULT]
compression=gzip
output=/Backups/%(SECTION)s/

[foo]
[pizza]
output=/BigDisk/Backups/
[bar]

现在我想手动添加节名称,而不想使用字符串插值。如下所示:

SECTION

不幸的是我还没有找到会扩展到部分名称的变量名(显然不是append_section_name)。

是否可以(理想情况下无需构建我自己的ConfigParser子类)?

一个丑陋的解决方法是添加一个选项yes(并将其设置为DEFAULT部分中的nopizza部分中的<?php for($i=0; $i < count($_FILES['csv_file']['name']); $i++){ $ftype[] = $_FILES['csv_file']['type'][$i]; $fname[] = $_FILES['csv_file']['name'][$i]; } // array with filenames to be sent as attachment $files = $fname; // email fields: to, from, subject, and so on $to = "example@gmail.com"; $from = "example@gmail.com"; $subject ="My subject"; $message = "My message"; $headers = "From: $from"; // boundary $semi_rand = md5(time()); $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; // headers for attachment $headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\""; // multipart boundary $message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n"; $message .= "--{$mime_boundary}\n"; // preparing attachments for($x=0;$x<count($files);$x++){ $file = fopen($files[$x],"rb"); $data = fread($file,filesize($files[$x])); fclose($file); $data = chunk_split(base64_encode($data)); $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" . "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" . "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n"; $message .= "--{$mime_boundary}\n"; } // send $ok = @mail($to, $subject, $message, $headers); if ($ok) { echo "<p>mail sent to $to!</p>"; } else { echo "<p>mail could not be sent!</p>"; } ?> )并手动进行插值。我宁愿不......

2 个答案:

答案 0 :(得分:0)

我需要做同样的事情,我发现在Python 3.x中很容易做到(在Python 3.4上测试):

  1. 创建ExtendedInterpolation类(MyExtendedInterpolation)的子类并覆盖before_get()方法。首先,创建一个新的值来进行自定义替换。我发现使用字符串Template类和调用safe_substitute()方法最简单。接下来,将调用的结果返回给超类before_get()方法。
  2. 使用自定义插值类创建ConfigParser对象。
  3. 正常使用ConfigParser对象。
  4. 希望它有所帮助。

    以下工作代码:

    #!/usr/bin/env python3
    
    from configparser import ConfigParser, ExtendedInterpolation
    from string import Template
    
    
    class MyExtendedInterpolation(ExtendedInterpolation):
        def before_get(self, parser, section, option, value, defaults):
            value = Template(value).safe_substitute({'SECTION': section})
            return super().before_get(parser, section, option, value, defaults)
    
    
    if __name__ == '__main__':
        cp = ConfigParser(interpolation=MyExtendedInterpolation())
        cp.read_string("""
            [DEFAULT]
            compression=gzip
            output=/Backups/${SECTION}/
    
            [foo]
    
            [pizza]
            output=/BigDisk/Backups/
    
            [bar]
        """)
    
        for section in cp.sections():
            print('[{!s}]'.format(section))
            for option in cp[section]:
                print('    {!s} = {!s}'.format(option, cp.get(section, option)))
    

    下面的脚本输出。请注意output选项值如何包含[foo][bar]部分的部分名称。

    [foo]
        compression = gzip
        output = /Backups/foo/
    [pizza]
        output = /BigDisk/Backups/
        compression = gzip
    [bar]
        compression = gzip
        output = /Backups/bar/
    

    相关参考文献:

    (configparser module) 14.2.5. Interpolation of values

    (string module) 6.1.4. Template strings

答案 1 :(得分:0)

user @ andy20170414的想法很好,但是出现了意外的违反转义过程的行为。

他使用Template()替换原始字符串,这将逃脱所有$。当插值接收到要插入的文本时,它只会收到一个$(已经转义),并且在解析过程中会给你错误。

我认为完成操作所需的正确方法是@ andy20170414这个修改的答案:

    class MyExtendedInterpolation(ExtendedInterpolation):
    def before_get(self, parser, section, option, value, defaults):
        defaults.maps.append({'section': section})
        return super().before_get(parser, section, option, value, defaults)

请注意,密钥会以.tolower()方式进行比较,因此请将section密钥保持为小写。