群里面的朋友提到是否应该出点题目给新加入python的朋友。我想值得一试。
本周题目如下:
读写配置文件是经常碰到操作,请大家写出自己读写配置文件的程序,要求:
1、配置文件可以以#作为注释,并不处理。
2、所写的程序应以import导入使用。
3、有自测试代码。
4、有注释。
希望大家踊跃参加。
honbj 回复于:2005-08-23 11:37:16
引用:原帖由 "xichen" 发表: 群里面的朋友提到是否应该出点题目给新加入python的朋友。我想值得一试。
本周题目如下:
读写配置文件是经常碰到操作,请大家写出自己读写配置文件的程序,要求:
1、配置文件可以以#作为注释,并不处理。
2?.........
创意很好 支持!希望能够坚持下来。
题目出的是不是有点泛,能否更细化一些,例如给出一个特定的配置文件。
这样大家便于交流比较。
纯属个人意见,仅供参考。
limodou 回复于:2005-08-23 16:57:04
版主的意思是希望有自定的格式,没必要千篇一律,当然如果你不知道使用什么好完全可以考虑标准的格式,如:ini,xml都可以。
xichen 回复于:2005-08-23 19:58:59
好象关注的人多,但是真正动手写的人少.一方面新手老说没有项目可以联系,一方面却不愿意花精神和时间来些,真让人郁闷.
可能被老师教惯了吧.总想google到最直接的答案.
limodou 回复于:2005-08-23 20:16:38
呵呵。求人不如求已呀。
wolfg 回复于:2005-08-23 21:07:05
引用:原帖由 "xichen" 发表: 好象关注的人多,但是真正动手写的人少.一方面新手老说没有项目可以联系,一方面却不愿意花精神和时间来些,真让人郁闷.
可能被老师教惯了吧.总想google到最直接的答案.
能想到用google就不错了,更直接的是朝人要,呵呵
honbj 回复于:2005-08-24 13:54:01
引用:原帖由 "limodou"]版主的意思是希望有自定的格式,没必要千篇一律,当然如果你不知道使用什么好完全可以考虑标准的格式,如:ini,xml都可以。 发表:
还真不知道什么是标准的格式,要不劳驾你给一个标准格式的配置文件吧
不必千篇一律 这个我自己用 :P
sakulagi 回复于:2005-08-24 15:11:17
爱学习的新手来了 :)
俺是彻底的新手。如果写的有问题,不要笑
#! /usr/bin/python
import os
import sys
class property:
""" Assume that property file is "ARG=VALUE" format and no space is allowed on either side of \"=\" """
def __init__(self, pfile):
f = open(pfile, "r")
linel = f.readlines()
list = map(self.split, linel)
#remove comments marker
if list.count(None) >; 0:
list.remove(None)
self.dict = dict(tuple(list))
def split(self, str):
# remove newline
str = str.strip("\n")
# remove blank spaces
str = str.strip()
# Treat comments separately
if str.startswith("#"):
r = None
else:
# At most 2 parts
r = str.split("=", 1)
r = map(self.stripbs, r)
return r
def stripbs(self, str):
return str.strip()
def getdict(self):
return self.dict
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 = property("test.properties");
else:
pf = property(sys.argv[1])
print pf.getdict();
xichen 回复于:2005-08-24 15:13:15
下周一我贴出我写的。
sakulagi 回复于:2005-08-24 15:15:18
好啊。等着看xichen老大的。呵呵
limodou 回复于:2005-08-24 16:16:46
to sakulagi:
你的程序写法与我的确不同。有一点建议:property在New Style Class 是有特殊用法的,它是一个内置(built-in)方法,最好不用它用为类名。另外你测试的最后一行多了一个';'号
limodou 回复于:2005-08-24 16:25:52
下面是我根据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:21
我的,呵呵,别笑话。
ini文件的格式参照了这里 http://en.wikipedia.org/wiki/Ini_file
也参考了Python的ConfigParser模块的文档
IniFileParser.py
#!C:\Python24\python.exe
import re
import string
NoSectionException = 'NoSectionException'
NoKeyException = 'NoKeyException'
class IniFileParser:
'''parse ini file described in http://en.wikipedia.org/wiki/Ini_file. no functions for write, only read. :)'''
def __init__(self):
self.section_obj = dict()
def load(self, filename):
f = open(filename, 'r')
while 1:
line = f.readline()
if not line: break
line = line.strip('\n')
line = line.strip()
# skip comments
if line == "" or line.startswith(';') or line.startswith('#'):
continue
match_section = re.compile(r'^\[([\w\s\.]*)\]$').match(line)
if match_section: # section name line
line = match_section.group(1) # get section name
sec_keys = dict()
self.section_obj[line] = sec_keys
else: # key=value line
re_comment = re.compile(r'[;#].*')
line = re_comment.sub('', line) # remove comments in line
[key, value] = map(string.strip, line.split('=', 1))
sec_keys[key] = value
f.close()
def sections(self):
result = self.section_obj.keys()
result.sort()
return result
def has_section(self, section):
return section in self.section_obj.keys()
def keys(self, section):
if not self.has_section(section): raise NoSectionException
result = self.section_obj[section].keys()
result.sort()
return result
def has_key(self, section, key):
return self.section_obj[section].has_key(key)
def get_value(self, section, key):
if not self.has_section(section): raise NoSectionException
if not self.has_key(section, key): raise NoKeyException
return self.section_obj[section][key]
Unit Test: TestIniFileParser.py
#!C:\Python24\python.exe
import unittest
from IniFileParser import *
class TestIniFileParser(unittest.TestCase):
def setUp(self):
self.ini = IniFileParser()
self.ini.load('test.ini')
def testsections(self):
self.assertEqual(self.ini.sections(), ['section1', 'section2'])
def testhassections(self):
self.assertTrue(self.ini.has_section('section1'))
self.assertTrue(self.ini.has_section('section2'))
self.assertFalse(self.ini.has_section('section3'))
def testkeys(self):
self.assertEqual(self.ini.keys('section1'), ['var1', 'var2'])
self.assertEqual(self.ini.keys('section2'), ['var1', 'var2'])
self.assertRaises(NoSectionException, self.ini.keys, 'section3')
def testhaskey(self):
self.assertTrue(self.ini.has_key('section1', 'var1'))
self.assertTrue(self.ini.has_key('section1', 'var2'))
self.assertTrue(self.ini.has_key('section2', 'var1'))
self.assertTrue(self.ini.has_key('section2', 'var2'))
def testgetvalue(self):
self.assertEqual(self.ini.get_value('section1', 'var1'), 'foo')
self.assertEqual(self.ini.get_value('section1', 'var2'), 'doodle')
self.assertEqual(self.ini.get_value('section2', 'var1'), 'baz')
self.assertEqual(self.ini.get_value('section2', 'var2'), 'shoodle')
self.assertRaises(NoSectionException, self.ini.get_value, 'section3', 'var1')
self.assertRaises(NoKeyException, self.ini.get_value, 'section1', 'var3')
if __name__ == '__main__':
#unittest.main()
suite = unittest.makeSuite(TestIniFileParser)
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:23
引用:原帖由 "limodou" 发表: to sakulagi:
你的程序写法与我的确不同。有一点建议:property在New Style Class 是有特殊用法的,它是一个内置(built-in)方法,最好不用它用为类名。另外你测试的最后一行多了一个';'号 :) 我也猜这么好听的名字一定有人用过了,呵呵
分号是因为我是一直写Java程序的 ,所以习惯了:oops:
sakulagi 回复于:2005-08-25 07:59:30
引用:原帖由 "limodou" 发表: print pf.getdict()
这里最后我的生成test.properties与原程序不同,因为发现在里面的双引号也输出到文件中去了,因此我去掉了。 还是用循环看着简洁。我本来想练习一下map(),结果不会写lambda函数,最后越写感觉越诡秘。嘿嘿
sakulagi 回复于:2005-08-25 08:02:03
引用:原帖由 "wolfg"] 发表: 相比之下俺写的果然简陋,嘿嘿。
依赛特小子 回复于:2005-08-27 16:19:25
什么是自测试代码?不理解自测的功能?
xichen 回复于:2005-08-28 21:42:15
Python 的两个用于单元测试的标准模块:unittest和doctest。这些模块扩展了用来确认函数内部的先置条件和后置条件的内置 assert 语句的能力。
由于模块是被import的,那么需要在直接运行该模块的时候检查必须的环境是否具备,并运行一段测试代码确保程序无错误.
一般采用
if __name__ == "__main__":
测试代码
这样的方法.
hardcorn 回复于:2005-08-29 09:32:49
学习
xichen 回复于:2005-08-29 11:44:10
只是我的看法而已,其实各位写的都有自己的特色。
config.py,这个是模块
# -*- coding: cp936 -*-
"""
本程序为MIT授权
作者:梅劲松
"""
"""
The MIT License
Copyright (c) 2005 stephen.cn@gmail.com
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:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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.
Read config module.
"""
__all__ = ['read_config']
__version__ = '1.0'
def read(file=''):
'''File name. String'''
if file=='':
return ('不能打开配置文件,请检查目录中是否有%s这个文件。\n' % file)
else:
config = get(file)
if not config:
return ('不能打开配置文件,请检查目录中是否有%s这个文件。\n' % file)
else:
return config
def get(file):
try:
fd = open(file)
except:
return None
lines = fd.readlines()
config = {}
for i in lines:
i = i.strip()
if i.find('=') < 0:
continue
if i[0] == '#':
continue
var, value = i.split('=',1)
var = var.strip()
value = value.split('=')
config[var] = value
return config
def _test():
import doctest, config
return doctest.testmod(config)
if __name__ == "__main__":
_test()
然后还有test.txt这个用来测试的文件
name=梅劲松
age=32
sex=男
iq=傻瓜
然后测试方式为在msdos方式下:
D:\>;python config.py -v
Running config.__doc__
0 of 0 examples failed in config.__doc__
Running config._test.__doc__
0 of 0 examples failed in config._test.__doc__
Running config.get.__doc__
0 of 0 examples failed in config.get.__doc__
Running config.read.__doc__
0 of 0 examples failed in config.read.__doc__
4 items had no tests:
config
config._test
config.get
config.read
0 tests in 4 items.
0 passed and 0 failed.
Test passed.
D:\>;
使用方法为
D:\>;python
Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>;>;>; import config
>;>;>; conf=config.read('test.txt')
>;>;>; conf['ai']
['\xc9\xb5\xb9\xcf']
>;>;>;
欢迎大家指正。
快乐叛逆者 回复于:2005-09-05 09:18:24
年轻人认真点
喜欢穿拖鞋 回复于:2005-09-06 08:45:27
我是想学这个语言,但我没有学过其他语言,请问会有什么障碍吗?如果有,请问学什么语言好呢?
wolfg 回复于:2005-09-06 09:12:35
引用:原帖由 "喜欢穿拖鞋"]我是想学这个语言,但我没有学过其他语言,请问会有什么障碍吗?如果有,请问学什么语言好呢? 发表: 不会有什么障碍,不过有些面向对象的概念更好。学什么语言得看适合你的情况,什么目的。
skyvoice 回复于:2005-11-28 21:01:18
不是说写自己的配置文件不好,建议用XML来编写配置文件,这样通用性更强些!
limodou 回复于:2005-11-28 21:24:42
不同的问题需要不同的方法。有些东西使用xml文件,读起来麻烦,写起来麻烦,用起来麻烦。够用就是好的。
jkit 回复于:2005-11-29 13:14:38
也来凑个热闹
支持默认值和多行属性
'''
The <code>Properties</code> class represents a persistent set of
properties. The <code>Properties</code> can be saved to a stream
or loaded from a stream. Each key and its corresponding value in
the property list is a string.
<p>
A property list can contain another property list as its
"defaults"; this second property list is searched if
the property key is not found in the original property list.
</p>
'''
class Properties:
def __init__(self, prop={}, default={}):
self.prop = prop
self.default = default
def put(self, key, value):
self.prop[key] = value
def get(self, key, default=None):
return self.prop.get(key, self.default.get(key, default))
def load(self, filename):
import os
if os.path.exists(filename) and os.path.isfile(filename):
fd = open(filename, 'r')
lines = fd.readlines()
fd.close()
keyvalue = ''
continueLine = False
for i in range(len(lines)):
line = lines.strip()
if line[0] == '#':
continue
if continueLine:
if line[-1:] == '\\':
line = line[:-1]
keyvalue += line
continue
else:
keyvalue += line
continueLine = False
else:
if line[-1:] == '\\':
keyvalue = line[:-1]
continueLine = True
continue
else:
keyvalue = line
continueLine = False
if keyvalue.find('=') < 0:
continue
key, value = keyvalue.split('=', 1)
self.prop[key.strip()] = value.strip()
if __name__ == '__main__':
p = Properties({'propname':'propname'}, {'defaultname':'defaultname'})
p.load('test.properties')
print p.get('noname'), p.get('noname', 'default-name')
print p.get('name'), p.get('name', 'default-name')
print p.get('propname'), p.get('propname', 'default-name')
print p.get('defaultname'), p.get('defaultname', 'default-name')
print p.get('value'), p.get('value', 'default-value')
用于测试的test.properties文件内容
# Properties test
name = properties name
value = multi-\
line \
value \
properties
dirty lines
# noname = end lines
[ 本帖最后由 jkit 于 2005-11-29 14:35 编辑 ]
limodou 回复于:2005-11-29 13:25:47
dict4ini
http://wiki.woodpecker.org.cn/moin/Dict4Ini
一个把ini当成字典使用的ini处理模块
wyting 回复于:2005-12-07 11:38:46
就用dict4ini了
|