用户友好的方式处理python中的配置文件?

时间:2011-05-12 15:05:01

标签: python configuration

我想编写一个程序,在发生特定事件时向一个或多个指定的收件人发送电子邮件。为此,我需要用户将邮件服务器的参数写入配置。可能的值例如是:serveradress,ports,ssl(true / false)和所需收件人列表。

用户最友好/最佳实践的方法是什么?

我当然可以使用带有正确参数的python文件,用户必须填写它,但我不认为这个用户友好。我也读过python中的'config'模块,但在我看来,它是为自己创建配置文件而制作的,而不是让用户自己填充文件。

4 个答案:

答案 0 :(得分:4)

你是说配置文件需要有效的Python这一事实使它不友好吗?它似乎在文件中包含行:

 server = 'mail.domain.com'
 port = 25

...等足够直观,同时仍然是有效的Python。但是,如果您不希望用户必须知道他们必须引用字符串,那么您可能会使用YAML路由。我几乎只使用YAML配置文件并发现它非常直观,而且我认为它对于最终用户来说也很直观(虽然它需要第三方模块 - PyYAML):

 server: mail.domain.com
 port: 25

加载pyyaml很简单:

>>> import yaml
>>> yaml.load("""a: 1
... b: foo
... """)
{'a': 1, 'b': 'foo'}

使用文件也很容易。

>>> with open('myconfig.yaml', 'r') as cfile:
...    config = yaml.load(cfile)
... 

config现在包含所有参数。

答案 1 :(得分:2)

我的用户技术熟练并不重要;你可以指望它们搞砸了编辑文本文件。 (他们会将它保存在错误的地方。他们将使用MS Word编辑文本文件。他们会打字错误。)我建议制作一个验证输入的gui并以正确的格式和位置创建配置文件。在Tkinter创建的简单gui可能符合您的需求。

答案 2 :(得分:1)

这种解决方案的缺点是什么:

ch = 'serveradress = %s\nport = %s\nssl = %s'

a = raw_input("Enter the server's address : ")

b = 'a'
bla = "\nEnter the port : "
while not all(x.isdigit() for x in b):
    b = raw_input(bla)
    bla = "Take care: you must enter digits exclusively\n"\
          +"  Re-enter the port (digits only) : "

c = ''
bla = "\nChoose the ssl option (t or f) : "
while c not in ('t','f'):
    c = raw_input(bla)
    bla = "Take care: you must type f or t exclusively\n"\
          +"  Re-choose the ssl option : "


with open('configfile.txt','w') as f:
    f.write(ch % (a,b,c))

PS

我在jonesy的帖子中读到可能必须引用配置文件中的值。如果是这样,并且您希望用户不必为他/她自己写引号,则只需添加

即可
a = a.join('""')
b = b.join('""')
c = c.join('""')

修改

ch = 'serveradress = %s\nport = %s\nssl = %s'

d = {0:('',
        "Enter the server's address : "),
     1:("Take care: you must enter digits exclusively",
        "Enter the port : "),
     2:("Take care: you must type f or t exclusively",
        "Choose the ssl option (t or f) : ")  }

def func(i,x):
    if x is None:
        return False
    if i==0:
        return True
    elif i==1:
        try:
            ess = int(x)
            return True
        except:
            return False
    elif i==2:
        if x in ('t','f'):
            return True
        else:
            return False


li = len(d)*[None]
L = range(len(d))

while True:

    for n in sorted(L):
        bla = d[n][1]
        val = None
        while not func(n,val):
            val = raw_input(bla)
            bla = '\n  '.join(d[n])
        li[n] = val.join('""')

    decision = ''
    disp = "\n====== If you choose to process, =============="\
           +"\n    the content of the file will be :\n\n" \
           + ch % tuple(li) \
           + "\n==============================================="\
           + "\n\nDo you want to process (type y) or to correct (type c) : "
    while decision not in ('y','c'):
        decision = raw_input(disp)
        disp = "Do you want to process (type y) or to correct (type c) ? : "

    if decision=='y':
        break
    else:
        diag = False
        while not diag:
            vi = '\nWhat lines do you want to correct ?\n'\
                 +'\n'.join(str(j)+' - '+line for j,line in enumerate((ch % tuple(li)).splitlines()))\
                 +'\nType numbers of lines belonging to range(0,'+str(len(d))+') separated by spaces) :\n'
            to_modify = raw_input(vi)
            try:
                diag = all(int(entry) in xrange(len(d)) for entry in to_modify.split())
                L = [int(entry) for entry in to_modify.split()]
            except:
                diag = False


with open('configfile.txt','w') as f:
    f.write(ch % tuple(li))

print '-*-  Recording of the config file : done  -*-'

答案 3 :(得分:1)

我一直在使用ConfigParser。它旨在读取具有以下内容的 .ini 样式文件。

[section]
option = value

它非常易于使用,文档非常易于阅读。基本上你只需将整个文件加载到ConfigParser对象中:

import ConfigParser    

config = ConfigParser.ConfigParser()
config.read('configfile.txt')

然后,您可以通过选中选项确保用户没有搞砸任何事情。我这样做有一个清单:

OPTIONS = 
    ['section,option,defaultvalue',
     .
     .
     .
    ]

for opt in OPTIONS:
    section,option,defaultval = opt.split(',')
    if not config.has_option(section,option):
        print "Missing option %s in section %s" % (option,section)

获取价值也很容易。

val = config.get('section','option')

我还编写了一个使用 OPTIONS 列表创建示例配置文件的函数。

    new_config = ConfigParser.ConfigParser()
    for opt in OPTIONS:
        section,option,defaultval = opt.split(',')
        if not new_config.has_section(section):
            new_config.add_section(section)
        new_config.set(section, option, defaultval)
    with open("sample_configfile.txt", 'wb') as newconfigfile:
        new_config.write(newconfigfile)
    print "Generated file: sample_configfile.txt"