Chinaunix

标题: 每周一题——读写配置文件。 [打印本页]

作者: xichen    时间: 2005-08-20 16:56
标题: 每周一题——读写配置文件。
群里面的朋友提到是否应该出点题目给新加入python的朋友。我想值得一试。

本周题目如下:
读写配置文件是经常碰到操作,请大家写出自己读写配置文件的程序,要求:
1、配置文件可以以#作为注释,并不处理。
2、所写的程序应以import导入使用。
3、有自测试代码。
4、有注释。

希望大家踊跃参加。
作者: honbj    时间: 2005-08-23 11:37
标题: 每周一题——读写配置文件。
原帖由 "xichen" 发表:
群里面的朋友提到是否应该出点题目给新加入python的朋友。我想值得一试。

本周题目如下:
读写配置文件是经常碰到操作,请大家写出自己读写配置文件的程序,要求:
1、配置文件可以以#作为注释,并不处理。
2?.........


创意很好 支持!希望能够坚持下来。

题目出的是不是有点泛,能否更细化一些,例如给出一个特定的配置文件。
这样大家便于交流比较。

纯属个人意见,仅供参考。
作者: limodou    时间: 2005-08-23 16:57
标题: 每周一题——读写配置文件。
版主的意思是希望有自定的格式,没必要千篇一律,当然如果你不知道使用什么好完全可以考虑标准的格式,如:ini,xml都可以。
作者: xichen    时间: 2005-08-23 19:58
标题: 每周一题——读写配置文件。
好象关注的人多,但是真正动手写的人少.一方面新手老说没有项目可以联系,一方面却不愿意花精神和时间来些,真让人郁闷.
可能被老师教惯了吧.总想google到最直接的答案.
作者: limodou    时间: 2005-08-23 20:16
标题: 每周一题——读写配置文件。
呵呵。求人不如求已呀。
作者: wolfg    时间: 2005-08-23 21:07
标题: 每周一题——读写配置文件。
原帖由 "xichen" 发表:
好象关注的人多,但是真正动手写的人少.一方面新手老说没有项目可以联系,一方面却不愿意花精神和时间来些,真让人郁闷.
可能被老师教惯了吧.总想google到最直接的答案.


能想到用google就不错了,更直接的是朝人要,呵呵
作者: honbj    时间: 2005-08-24 13:54
标题: 每周一题——读写配置文件。
[quote]原帖由 "limodou"]版主的意思是希望有自定的格式,没必要千篇一律,当然如果你不知道使用什么好完全可以考虑标准的格式,如:ini,xml都可以。[/quote 发表:



还真不知道什么是标准的格式,要不劳驾你给一个标准格式的配置文件吧
不必千篇一律 这个我自己用  
作者: sakulagi    时间: 2005-08-24 15:11
标题: 每周一题——读写配置文件。
爱学习的新手来了

俺是彻底的新手。如果写的有问题,不要笑

  1. #! /usr/bin/python

  2. import os
  3. import sys

  4. class property:
  5.         """ Assume that property file is "ARG=VALUE" format and no space is allowed on either side of \"=\" """
  6.         def __init__(self, pfile):
  7.                 f = open(pfile, "r")
  8.                 linel = f.readlines()
  9.                 list = map(self.split, linel)
  10.                 #remove comments marker
  11.                 if list.count(None) >; 0:
  12.                         list.remove(None)
  13.                 self.dict = dict(tuple(list))

  14.         def split(self, str):
  15.                 # remove newline
  16.                 str = str.strip("\n")
  17.                 # remove blank spaces
  18.                 str = str.strip()
  19.                 # Treat comments separately
  20.                 if str.startswith("#"):
  21.                         r = None
  22.                 else:
  23.                         # At most 2 parts
  24.                         r = str.split("=", 1)
  25.                         r = map(self.stripbs, r)
  26.                 return r

  27.         def stripbs(self, str):
  28.                 return str.strip()

  29.         def getdict(self):
  30.                 return self.dict


  31. if __name__ == "__main__":
  32.         print "Self Test Begin"
  33.         # Generate the test file
  34.         if len(sys.argv) == 1:
  35.                 os.system("echo \"# Comment\" >; test.properties")
  36.                 os.system("echo \"LOCK=true\" >;>; test.properties")
  37.                 os.system("echo \"TEST.config.1=234\" >;>; test.properties")
  38.                 pf = property("test.properties");
  39.         else:
  40.                 pf = property(sys.argv[1])
  41.         print pf.getdict();
复制代码

作者: xichen    时间: 2005-08-24 15:13
标题: 每周一题——读写配置文件。
下周一我贴出我写的。
作者: sakulagi    时间: 2005-08-24 15:15
标题: 每周一题——读写配置文件。
好啊。等着看xichen老大的。呵呵
作者: limodou    时间: 2005-08-24 16:16
标题: 每周一题——读写配置文件。
to sakulagi:

你的程序写法与我的确不同。有一点建议:property在New Style Class 是有特殊用法的,它是一个内置(built-in)方法,最好不用它用为类名。另外你测试的最后一行多了一个';'号
作者: limodou    时间: 2005-08-24 16:25
标题: 每周一题——读写配置文件。
下面是我根据sakulagi的思路改写的程序:

#! /usr/bin/python

import os
import sys

class Ini:
    """ Assume that property file is "ARG=VALUE" format and no space is allowed on either side of \"=\" """
    def __init__(self, pfile):
        self.items = {}
   
        for line in file(pfile):
            line = line.strip()
            if not line: continue
            if line.startswith('#'): continue
            key, value = line.split('=', 1)
            self.items[key.strip()] = value.strip()
   
    def getdict(self):
        return self.items


if __name__ == "__main__":
    print "Self Test Begin"
    # Generate the test file
    if len(sys.argv) == 1:
        os.system("echo # Comment >; test.properties"
        os.system("echo LOCK=true >;>; test.properties"
        os.system("echo TEST.config.1=234 >;>; test.properties"
        pf = Ini("test.properties";
    else:
        pf = Ini(sys.argv[1])
    print pf.getdict()

这里最后我的生成test.properties与原程序不同,因为发现在里面的双引号也输出到文件中去了,因此我去掉了。
作者: wolfg    时间: 2005-08-24 23:39
标题: 每周一题——读写配置文件。
我的,呵呵,别笑话。
ini文件的格式参照了这里 http://en.wikipedia.org/wiki/Ini_file
也参考了Python的ConfigParser模块的文档

IniFileParser.py

  1. #!C:\Python24\python.exe

  2. import re
  3. import string

  4. NoSectionException = 'NoSectionException'
  5. NoKeyException = 'NoKeyException'

  6. class IniFileParser:
  7.     '''parse ini file described in http://en.wikipedia.org/wiki/Ini_file. no functions for write, only read. :)'''
  8.     def __init__(self):
  9.         self.section_obj = dict()

  10.     def load(self, filename):
  11.         f = open(filename, 'r')
  12.         while 1:
  13.             line = f.readline()
  14.             if not line: break
  15.             line = line.strip('\n')
  16.             line = line.strip()
  17.             # skip comments
  18.             if line == "" or line.startswith(';') or line.startswith('#'):
  19.                 continue
  20.             match_section = re.compile(r'^\[([\w\s\.]*)\]$').match(line)
  21.             if match_section:   # section name line
  22.                 line = match_section.group(1) # get section name
  23.                 sec_keys = dict()
  24.                 self.section_obj[line] = sec_keys
  25.             else:               # key=value line
  26.                 re_comment = re.compile(r'[;#].*')
  27.                 line = re_comment.sub('', line) # remove comments in line
  28.                 [key, value] = map(string.strip, line.split('=', 1))
  29.                 sec_keys[key] = value
  30.                
  31.         f.close()

  32.     def sections(self):
  33.         result = self.section_obj.keys()
  34.         result.sort()
  35.         return result

  36.     def has_section(self, section):
  37.         return section in self.section_obj.keys()

  38.     def keys(self, section):
  39.         if not self.has_section(section): raise NoSectionException
  40.         result = self.section_obj[section].keys()
  41.         result.sort()
  42.         return result

  43.     def has_key(self, section, key):
  44.         return self.section_obj[section].has_key(key)

  45.     def get_value(self, section, key):
  46.         if not self.has_section(section): raise NoSectionException
  47.         if not self.has_key(section, key): raise NoKeyException
  48.         return self.section_obj[section][key]
复制代码


Unit Test: TestIniFileParser.py

  1. #!C:\Python24\python.exe

  2. import unittest
  3. from IniFileParser import *

  4. class TestIniFileParser(unittest.TestCase):
  5.     def setUp(self):
  6.         self.ini = IniFileParser()
  7.         self.ini.load('test.ini')

  8.     def testsections(self):
  9.         self.assertEqual(self.ini.sections(), ['section1', 'section2'])

  10.     def testhassections(self):
  11.         self.assertTrue(self.ini.has_section('section1'))
  12.         self.assertTrue(self.ini.has_section('section2'))
  13.         self.assertFalse(self.ini.has_section('section3'))

  14.     def testkeys(self):
  15.         self.assertEqual(self.ini.keys('section1'), ['var1', 'var2'])
  16.         self.assertEqual(self.ini.keys('section2'), ['var1', 'var2'])
  17.         self.assertRaises(NoSectionException, self.ini.keys, 'section3')

  18.     def testhaskey(self):
  19.         self.assertTrue(self.ini.has_key('section1', 'var1'))
  20.         self.assertTrue(self.ini.has_key('section1', 'var2'))
  21.         self.assertTrue(self.ini.has_key('section2', 'var1'))
  22.         self.assertTrue(self.ini.has_key('section2', 'var2'))

  23.     def testgetvalue(self):
  24.         self.assertEqual(self.ini.get_value('section1', 'var1'), 'foo')
  25.         self.assertEqual(self.ini.get_value('section1', 'var2'), 'doodle')
  26.         self.assertEqual(self.ini.get_value('section2', 'var1'), 'baz')
  27.         self.assertEqual(self.ini.get_value('section2', 'var2'), 'shoodle')
  28.         self.assertRaises(NoSectionException, self.ini.get_value, 'section3', 'var1')
  29.         self.assertRaises(NoKeyException, self.ini.get_value, 'section1', 'var3')

  30. if __name__ == '__main__':
  31.     #unittest.main()
  32.     suite = unittest.makeSuite(TestIniFileParser)
  33.     unittest.TextTestRunner(verbosity=2).run(suite)
复制代码


ini file for test: test.ini
[section1]

; some comment on section1
var1 = foo
var2 = doodle ; some comment on section1.var2

[section2]

# some comment on section2
var1 = baz # some comment on section2.var1
var2 = shoodle

# [section3]
# var1 = bar
; var2 =

作者: sakulagi    时间: 2005-08-25 07:58
标题: 每周一题——读写配置文件。
原帖由 "limodou" 发表:
to sakulagi:

你的程序写法与我的确不同。有一点建议:property在New Style Class 是有特殊用法的,它是一个内置(built-in)方法,最好不用它用为类名。另外你测试的最后一行多了一个';'号
我也猜这么好听的名字一定有人用过了,呵呵

分号是因为我是一直写Java程序的 ,所以习惯了
作者: sakulagi    时间: 2005-08-25 07:59
标题: 每周一题——读写配置文件。
原帖由 "limodou" 发表:
print pf.getdict()

这里最后我的生成test.properties与原程序不同,因为发现在里面的双引号也输出到文件中去了,因此我去掉了。
还是用循环看着简洁。我本来想练习一下map(),结果不会写lambda函数,最后越写感觉越诡秘。嘿嘿
作者: sakulagi    时间: 2005-08-25 08:02
标题: 每周一题——读写配置文件。
[quote]原帖由 "wolfg"][/quote 发表:
相比之下俺写的果然简陋,嘿嘿。
作者: 依赛特小子    时间: 2005-08-27 16:19
标题: 每周一题——读写配置文件。
什么是自测试代码?不理解自测的功能?
作者: xichen    时间: 2005-08-28 21:42
标题: 每周一题——读写配置文件。
Python 的两个用于单元测试的标准模块:unittest和doctest。这些模块扩展了用来确认函数内部的先置条件和后置条件的内置 assert 语句的能力。
由于模块是被import的,那么需要在直接运行该模块的时候检查必须的环境是否具备,并运行一段测试代码确保程序无错误.
一般采用

if __name__ == "__main__":
    测试代码
这样的方法.
作者: hardcorn    时间: 2005-08-29 09:32
标题: 每周一题——读写配置文件。
学习
作者: xichen    时间: 2005-08-29 11:44
标题: 每周一题——读写配置文件。
只是我的看法而已,其实各位写的都有自己的特色。

config.py,这个是模块
  1. # -*- coding: cp936 -*-

  2. """
  3. 本程序为MIT授权
  4. 作者:梅劲松
  5. """

  6. """
  7. The MIT License

  8. Copyright (c) 2005 stephen.cn@gmail.com

  9. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

  10. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


  12. Read config module.

  13. """

  14. __all__ = ['read_config']
  15. __version__ = '1.0'

  16. def read(file=''):
  17.     '''File name. String'''
  18.     if file=='':
  19.         return ('不能打开配置文件,请检查目录中是否有%s这个文件。\n' % file)
  20.     else:
  21.         config = get(file)
  22.         if not config:
  23.             return ('不能打开配置文件,请检查目录中是否有%s这个文件。\n' % file)
  24.         else:
  25.             return config
  26.             
  27. def get(file):
  28.     try:
  29.             fd = open(file)
  30.     except:
  31.             return None
  32.     lines = fd.readlines()
  33.     config = {}
  34.     for i in lines:
  35.             i = i.strip()
  36.             if i.find('=') < 0:
  37.                     continue
  38.             if i[0] == '#':
  39.                     continue
  40.             var, value = i.split('=',1)
  41.             var = var.strip()
  42.             value = value.split('=')
  43.             config[var] = value
  44.     return config


  45. def _test():
  46.     import doctest, config
  47.     return doctest.testmod(config)


  48. if __name__ == "__main__":
  49.     _test()
复制代码


然后还有test.txt这个用来测试的文件

  1. name=梅劲松
  2. age=32
  3. sex=男
  4. iq=傻瓜
复制代码

然后测试方式为在msdos方式下:

  1. D:\>;python config.py -v
  2. Running config.__doc__
  3. 0 of 0 examples failed in config.__doc__
  4. Running config._test.__doc__
  5. 0 of 0 examples failed in config._test.__doc__
  6. Running config.get.__doc__
  7. 0 of 0 examples failed in config.get.__doc__
  8. Running config.read.__doc__
  9. 0 of 0 examples failed in config.read.__doc__
  10. 4 items had no tests:
  11.     config
  12.     config._test
  13.     config.get
  14.     config.read
  15. 0 tests in 4 items.
  16. 0 passed and 0 failed.
  17. Test passed.

  18. D:\>;
复制代码

使用方法为

  1. D:\>;python
  2. Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on win32
  3. Type "help", "copyright", "credits" or "license" for more information.
  4. >;>;>; import config
  5. >;>;>; conf=config.read('test.txt')
  6. >;>;>; conf['ai']
  7. ['\xc9\xb5\xb9\xcf']
  8. >;>;>;
复制代码


欢迎大家指正。
作者: 快乐叛逆者    时间: 2005-09-05 09:18
标题: 每周一题——读写配置文件。
年轻人认真点
作者: 喜欢穿拖鞋    时间: 2005-09-06 08:45
标题: 每周一题——读写配置文件。
我是想学这个语言,但我没有学过其他语言,请问会有什么障碍吗?如果有,请问学什么语言好呢?
作者: wolfg    时间: 2005-09-06 09:12
标题: 每周一题——读写配置文件。
[quote]原帖由 "喜欢穿拖鞋"]我是想学这个语言,但我没有学过其他语言,请问会有什么障碍吗?如果有,请问学什么语言好呢?[/quote 发表:
不会有什么障碍,不过有些面向对象的概念更好。学什么语言得看适合你的情况,什么目的。
作者: skyvoice    时间: 2005-11-28 21:01
不是说写自己的配置文件不好,建议用XML来编写配置文件,这样通用性更强些!
作者: limodou    时间: 2005-11-28 21:24
不同的问题需要不同的方法。有些东西使用xml文件,读起来麻烦,写起来麻烦,用起来麻烦。够用就是好的。
作者: jkit    时间: 2005-11-29 13:14
也来凑个热闹
支持默认值和多行属性


  1. '''
  2. The <code>Properties</code> class represents a persistent set of
  3. properties. The <code>Properties</code> can be saved to a stream
  4. or loaded from a stream. Each key and its corresponding value in
  5. the property list is a string.
  6. <p>
  7. A property list can contain another property list as its
  8. "defaults"; this second property list is searched if
  9. the property key is not found in the original property list.
  10. </p>
  11. '''

  12. class Properties:
  13.     def __init__(self, prop={}, default={}):
  14.         self.prop = prop
  15.         self.default = default

  16.     def put(self, key, value):
  17.         self.prop[key] = value

  18.     def get(self, key, default=None):
  19.         return self.prop.get(key, self.default.get(key, default))

  20.     def load(self, filename):
  21.         import os
  22.         if os.path.exists(filename) and os.path.isfile(filename):
  23.             fd = open(filename, 'r')
  24.             lines = fd.readlines()
  25.             fd.close()
  26.             keyvalue = ''
  27.             continueLine = False
  28.             for i in range(len(lines)):
  29.                 line = lines[i].strip()
  30.                 if line[0] == '#':
  31.                     continue
  32.                 if continueLine:
  33.                     if line[-1:] == '\\':
  34.                         line = line[:-1]
  35.                         keyvalue += line
  36.                         continue
  37.                     else:
  38.                         keyvalue += line
  39.                         continueLine = False
  40.                 else:
  41.                     if line[-1:] == '\\':
  42.                         keyvalue = line[:-1]
  43.                         continueLine = True
  44.                         continue
  45.                     else:
  46.                         keyvalue = line
  47.                         continueLine = False
  48.                 if keyvalue.find('=') < 0:
  49.                     continue
  50.                 key, value = keyvalue.split('=', 1)
  51.                 self.prop[key.strip()] = value.strip()

  52. if __name__ == '__main__':
  53.     p = Properties({'propname':'propname'}, {'defaultname':'defaultname'})
  54.     p.load('test.properties')
  55.     print p.get('noname'), p.get('noname', 'default-name')
  56.     print p.get('name'), p.get('name', 'default-name')
  57.     print p.get('propname'), p.get('propname', 'default-name')
  58.     print p.get('defaultname'), p.get('defaultname', 'default-name')
  59.     print p.get('value'), p.get('value', 'default-value')

复制代码


用于测试的test.properties文件内容
  1. # Properties test
  2. name = properties name
  3. value = multi-\
  4.         line \
  5.         value \
  6.         properties
  7. dirty lines
  8. # noname = end lines
复制代码

[ 本帖最后由 jkit 于 2005-11-29 14:35 编辑 ]
作者: limodou    时间: 2005-11-29 13:25
dict4ini

http://wiki.woodpecker.org.cn/moin/Dict4Ini

一个把ini当成字典使用的ini处理模块
作者: wyting    时间: 2005-12-07 11:38
就用dict4ini了
作者: yikalu    时间: 2008-04-08 12:29
提示: 作者被禁止或删除 内容自动屏蔽
作者: shhgs    时间: 2008-04-10 17:50
Py比xml简单,凭什么要用xml做配置文件?

这个题目很不错的。如果是标准答案,是不是我也贡献一个?
作者: chrisyan    时间: 2008-04-11 00:16
本来还想写一个,一看大家都是05年写的,惭愧惭愧,还是算了
作者: still48    时间: 2008-04-14 23:38
标题: 回复 #1 xichen 的帖子
我也是新手,而且是完全没基础的新手

非常不好意思的问一下,什么是配置文件?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2