2007年11月06日 星期二 18:50
Hello,
Recently I'm working on a new data structure written in python: Tree,
by operator overloading. I want it can act as a builtin type, such as
list and dict, but do something like a tree, to make those things need
trees can be more convenient.
For example,
1. to create a Tree, there are several ways:
(1) A empty Tree:
>>> root = Tree(None)
>>> print root
** Tree **
() : None,
(2) A tree like this:
root('zero')
\--trunk('a')
\--branch(1)
>>> root = Tree('zero', trunk='a', branch=1)
>>> print root
** Tree **
('trunk',) : 'a',
() : 'zero',
('branch',) : 1,
(3) With items:
>>> root = Tree('zero', trunk='a', branch=1, _node_items={'try' : 'x'})
>>> print root
** Tree **
('trunk',) : 'a',
() : 'zero',
(('try',),) : 'x',
('branch',) : 1,
or like this:
>>> root = Tree('value', {'x' : 'v1', 'y' : 2}, trunk='v3', branch=4)
>>> print root
** Tree **
('trunk',) : 'v3',
() : 'value',
(('y',),) : 2,
('branch',) : 4,
(('x',),) : 'v1',
The items can be considered as attributes of a Tree node, something like
XML attr? '')
(4) A more complicated one:
>>> root = Tree('value', {'x' : 'v1', 'y' : Tree(2, {'z' : 'v3'}, br=4)},
trunk='v5', branch=Tree(6, {'a' : 'v7'}, br=8))
>>> print root
** Tree **
('branch', ('a',)) : 'v7',
(('y',),) : 2,
('branch',) : 6,
('branch', 'br') : 8,
('trunk',) : 'v5',
(('x',),) : 'v1',
(('y', 'z'),) : 'v3',
() : 'value',
(('y',), 'br') : 4,
2. Or create a Tree with setattr syntax :
>>> root = Tree(None)
>>> root = Tree('value')
>>> root['x'] = 'v1'
>>> root['y'] = 2
>>> root.trunk = 'v5'
>>> root.branch = 6
>>> root['x']['z'] = 'v3'
>>> root['x'].br = 4
>>> root.branch['a'] = 'v7'
>>> root.branch.br = 8
>>> print root
** Tree **
('branch', ('a',)) : 'v7',
() : 'value',
(('y',),) : 2,
('branch',) : 6,
('branch', 'br') : 8,
('trunk',) : 'v5',
(('x', 'z'),) : 'v3',
(('x',),) : 'v1',
(('x',), 'br') : 4,
3. It's very simple to retrive the value of any given Tree node:
>>> print root
** Tree **
(('x', 'y'),) : 'xy',
(('y',),) : 3,
('branch',) : 7,
('trunk', ('a',)) : 5,
('trunk',) : 4,
(('x',),) : 1,
('trunk', ('a', 'b'), 'data') : ['trunk', 'ab', 6],
() : 0,
(('x',), 'data') : ['x', 2],
('trunk', ('a', 'b')) : 'trunk ab',
('trunk', ('a',), 'data') : 'a data',
('branch', 'data') : 8,
>>> root()
0
>>> root.trunk()
4
>>> root.branch()
7
>>> root['x']
>>> root['x']()
1
>>> root['x'].data()
['x', 2]
4. As you have seen, the "print" operation of course have traversed the
Tree. Traverse return a path sequences to nodes map(dict) --
Tree<http://crablfs.sourceforge.net/tree.html#Tree>
dict, every
item represents a single Tree<http://crablfs.sourceforge.net/tree.html#Tree>
node. It't better to be called by
__call__ <http://crablfs.sourceforge.net/tree.html#Tree-__call__>
('traverse'), for example:
root('traverse') will return:
treedict = {
{
() : Tree <http://crablfs.sourceforge.net/tree.html#Tree>(0),
(('x',),) : Tree <http://crablfs.sourceforge.net/tree.html#Tree>(1),
(('x',), 'data') : Tree<http://crablfs.sourceforge.net/tree.html#Tree>
(['x', 2]),
(('x', 'y'),) : Tree <http://crablfs.sourceforge.net/tree.html#Tree>
('xy'),
(('y',),) : Tree <http://crablfs.sourceforge.net/tree.html#Tree>(3),
('trunk',) : Tree <http://crablfs.sourceforge.net/tree.html#Tree>
(4),
('trunk', ('a',)) : Tree<http://crablfs.sourceforge.net/tree.html#Tree>
(5),
('trunk', ('a',), 'data') :
Tree<http://crablfs.sourceforge.net/tree.html#Tree>
("a data"),
('trunk', ('a', 'b')) :
Tree<http://crablfs.sourceforge.net/tree.html#Tree>
("trunk ab"),
('trunk', ('a', 'b'), 'data') :
Tree<http://crablfs.sourceforge.net/tree.html#Tree>
(['trunk', 'ab', 6]),
('branch',) : Tree <http://crablfs.sourceforge.net/tree.html#Tree>
(7),
('branch', 'data') : Tree<http://crablfs.sourceforge.net/tree.html#Tree>
(8)
}
5. Update a Tree with another one:
>>> def build_tree1():
root['x'] = '1x'
... root = Tree(0)
root.trunk['a'] = 5
... root['x'] = '1x'
root.branch.data.extra = ['extra', 'info']
... root['x'].data = 1
... root['x']['y'] = '1xy'
... root['x']['y'].data = 2
... root['y'] = 3
... root.trunk = 4
... root.trunk['a'] = 5
... root.trunk['a'].data = '5'
... root.trunk['x'] = '2x'
... root.trunk ['x'].data = 6
... root.trunk['x']['y'] = '2xy'
... root.trunk['x']['y'].data = 7
... root.branch = 8
... root.branch.data = 9
... root.branch.data.extra = ['extra', 'info']
... return root
...
>>> def build_tree2():
root['x'] = '1.x'
... root = Tree('0')
root.trunk['x'] = ' two.x'
... root['x'] = '1.x'
root.branch.new = 'attr.new'
return root... root['x'].data = '1'
... root['new'] = '1.new'
... root.trunk = '4'
... root.trunk['a'] = "a test"
... root.trunk['x'] = None
... root.trunk['b'] = 'b'
... root.trunk['x'] = ' two.x'
... root.trunk['x']['y'] = '2.xy'
... root.trunk['x']['y'].data = '7'
... root.trunk['new'] = '2.new'
... root.trunk['new'].data = ' 2.new.data'
... root.branch = '8'
... root.branch.new = 'attr.new'
... return root
...
>>> tree1 = build_tree1()
>>> tree2 = build_tree2()
Then you can update tree1 like these to build a new Tree:
>>> tree1('update', tree2)
>>> print tree1
** Tree **
('branch', 'data', 'extra') : ['extra', 'info'],
('branch', 'new') : 'attr.new',
('trunk', ('x', 'y')) : '2.xy',
('trunk', ('x',), 'data') : 6,
('branch',) : '8',
('trunk', ('x', 'y'), 'data') : '7',
(('x',), 'data') : '1',
('trunk',) : '4',
('trunk', ('new',), 'data') : ' 2.new.data',
('trunk', ('new',)) : '2.new',
('trunk', ('x',)) : 'two.x',
(('x',),) : '1.x',
('trunk', ('a',)) : 'a test',
() : '0',
(('y',),) : 3,
(('x', 'y'),) : '1xy',
('trunk', ('a',), 'data') : '5',
('trunk', ('b',)) : 'b',
('branch', 'data') : 9,
(('new',),) : '1.new',
(('x', 'y'), 'data') : 2,
You can also use "+=" operator to do this:
>>> tree1 = build_tree1()
>>> tree1 += tree2
>>> print tree1
** Tree **
('branch', 'data', 'extra') : ['extra', 'info'],
('branch', 'new') : 'attr.new ',
('trunk', ('x', 'y')) : '2.xy',
('trunk', ('x',), 'data') : 6,
('branch',) : '8',
('trunk', ('x', 'y'), 'data') : '7',
(('x',), 'data') : '1',
('trunk',) : '4',
('trunk', ('new',), 'data') : '2.new.data',
('trunk', ('new',)) : ' 2.new',
('trunk', ('x',)) : 'two.x',
(('x',),) : '1.x',
('trunk', ('a',)) : 'a test',
() : '0',
(('y',),) : 3,
(('x', 'y'),) : '1xy',
('trunk', ('a',), 'data') : '5',
('trunk', ('b',)) : 'b',
('branch', 'data') : 9,
(('new',),) : '1.new',
(('x', 'y'), 'data') : 2,
Or use "+" to build a new Tree:
>>> tree3 = tree1 + tree2
6. Compare 2 Trees:
Compare the root node value first, and if equal, compare their sub nodes,
attributes or items ...
7. Some other functions that have not been implemented ...
============
So far I use this Tree as a direct configuration method. For instance,
in my another project cutils which has a tool to do realtime file system
mirroring, the configuration file is like this:
sh# cat /etc/python/fs_mirror
"""
The configuration file for fs_mirror
"""
import tree
options = tree.Tree('fs_mirror')
o = options
#o.mode = 'daemon'
# There can be other mode, such as "run_once"
#o.host = 'localhost'
#o.port = 2123
# The server runs mirrord
#o.timeout = 60
#o.daemon = None
#o.daemon.datadir = "/var/fs_mirror"
# The mirrored dirs/files will be put into this directory
#o.fssync = 'Report'
# The synchronization mechanism you choose, it can be one of:
# FTP, NFS, SMB/CIFS, SSH, RSYNC, ...
# REPORT only reports the actions in wmLog,
# does not do actual dirs creating or files transport
###o.fssync.host = 'localhost'
# Must be the same as o.host?
#o.fssync.port = 0
#o.fssync.user = 'root'
#o.fssync.passwd = ''
# Since it contains passord, you'd better keep this configuration file
secret.
# You can put the id/password pair to a secret file, such as
# ~/.fs_mirror/secret
# $host:$password
# and use --password-from ~/.fs_mirror/secret:$host
# option of fs_mirror script to appoint the password
# By this way, another user can not view the passwords by run "ps"
# when you appointed the it from the command line option.
# The reason a command line options is used is for multi-mirroring
And the script read and analyze this configuration file can be written
like this:
...
CONFIG_MODULE_PATH = "/etc/python"
...
options = tree.Tree('fs_mirror')
options.mode = 'daemon'
options.host = 'localhost'
options.port = 2123
options.timeout = 60
options.daemon = None
options.daemon.datadir = "/var/fs_mirror"
options.fssync = 'Report'
options.fssync.port = 0
options.fssync.user = 'root'
options.fssync.passwd = ''
# Update options from a configuration file:
try:
sys.path.insert (0, CONFIG_MODULE_PATH)
try:
import fs_mirror_config as config
options('update', config.options)
except ImportError:
pass
sys.path.pop(0)
except tree.TreeExc, trexc:
strerr = "Invalid option because of: %s" % trexc.msg
print >> sys.stderr, strerr
syslog.syslog(syslog.LOG_ERR, strerr)
sys.exit (1)
# Update options from command line parameters:
opts, args = getopt.gnu_getopt(sys.argv[1:], 'm:h:p:t:o:v',
['mode=', 'host=', 'port=', 'timeout=', 'option=', 'datadir=',
'help', 'verbose', 'password-from='])
if args:
options.identities = args
ov = []
for o, v in opts:
if o == '-m' or o == '--mode':
options.mode = v
elif o == '-h' or o == '--host':
options.host = v
elif o == '-p' or o == '--port':
options.port = int(v)
elif o == '-t' or o == '--timeout':
options.timeout = int(v)
elif o == "--datadir":
options.daemon.datadir = v
elif o == '-o' or o == '--option':
ov.append(v)
elif o == '--help':
print usage
sys.exit(0)
elif o == '-v' or o == '--verbose':
fs_mirror.debug = 1
fs_sync.debug = 1
elif o == '--password-from':
try:
fname, hostid = v.split(':')
except ValueError:
raise ValueError, "Invalid secret-file:id pair for
--passwd-from"
for line in open(fname, 'r'):
line = line.strip()
try:
id, passwd = line.split(':')
if id == hostid:
options.fssync.passwd = passwd
break
except ValueError:
raise ValueError, "Invalid id:password pair record '%s'"
% line
options('update', oparse(ov))
You can find the document of "cutils" project at:
http://crablfs.sourceforge.net <http://crablfs.sourceforge.net/tree.html>
/#ru_data_man
and download it from:
http://sourceforge.net/projects/crablfs
<http://crablfs.sourceforge.net/tree.html>
But I think this Tree structure can also be used in other ways. For
example, I think it's possible to implement an API to read XML into such
structure ...
============
Luckily the basic definition has been finished now, you can also download
it from:
http://sourceforge.net/projects/crablfs
the document is in the code and unittest. And I have put the HTML at:
http://crablfs.sourceforge.net/tree.html
The source code is in SVN:
https://crablfs.svn.sourceforge.net/svnroot/crablfs/caxes/trunk/ >
the files are tree.py and test_tree.py.
I hope this can be useful to you. Maybe I can write a PEP? Looking
forward to your suggestions and advices...
I'm not so expericenced, and this is only a partial finished work, since
I can only squash my limited spare time to do this and there is several
projects I have started. There are many things to learn, and now I'm
learning from you '')
Thank you.
--
------------------------------------------------------------------------
My Projects:
http://sourceforge.net/projects/crablfs
http://crablfs.sourceforge.net/
http://crablfs.sourceforge.net/#ru_data_man
http://crablfs.sourceforge.net/tree.html
http://cralbfs.sourceforge.net/sysadm_zh_CN.html
My Blog:
http://chowroc.blogspot.com/
http://hi.baidu.com/chowroc_z/
Looking for a space and platform to exert my originalities (for my
projects)...
-------------- ä¸ä¸é¨å --------------
??HTML?????...
URL: http://python.cn/pipermail/python-chinese/attachments/20071106/5706807f/attachment-0001.html
2007年11月07日 星期三 08:47
顺道去去sf上看了一下,最大的感想是文档真棒,难得看到国人做的开源项目能这么"专业":) 回到这个tree的模块,说几点我的想法: 第一印象,这大概不能算是一个"general purpose"的tree,这一点和内置的list和dict感觉不一样。在我的理解中,从数据结构的视角来看,tree的核心概念只有节点及其父子关系(root和leaf都是由此而来的衍生概念),基本操作只有节点的CRUD、遍历以及对整颗子树的移动,其它的都不能算是基本语义。 这个模块中大量使用key-value的语义来处理节点,对于单纯的"tree"来说其实是增加了不必要的复杂性。尤其是有些地方为了api的使用便利,让接口的语义变得模糊(attribute和items两种"子节点"的概念,multi-key和nested-key的同时支持,节点赋值时value和subtree的处理,都是很容易带来混淆的地方),个人觉得可能是得不偿失的。 我个人比较喜欢的方式是把这些核心的概念以及基础的api抽离出来作为一个基类,保持其简洁和单纯(这里我觉得用显式的方法声明会比用隐式的action分派更清晰一些),然后在不同应用场景(比如这里是用于配置管理)中使用不同扩展实现来提供一些便利的附加方法。 其实仅仅是为了表达这种有层次的信息的话,嵌套list/dict或者python自己的class大多数时候已经够用了,真正需要tree的时候多半是用到某种特定的存储结构(比如平衡树、B树、红黑树等等)来实现高效的CRUD操作,如果要作为基础库设计的话,这方面最好留下扩展的余地。至少,traverse返回iterable会比直接返回一个dict要好些。 当然,模块本身其实写得很漂亮,作者应该有相当的经验,这里只是想表达一下个人对api设计方面的不同理念。 On 11/6/07, Roc Zhou <chowroc.z+l at gmail.com> wrote: > Hello, > > Recently I'm working on a new data structure written in python: Tree, > by operator overloading. I want it can act as a builtin type, such as > list and dict, but do something like a tree, to make those things need > trees can be more convenient. > > For example, > 1. to create a Tree, there are several ways: > (1) A empty Tree: > >>> root = Tree(None) > >>> print root > ** Tree ** > () : None, > > (2) A tree like this: > root('zero') > \--trunk('a') > \--branch(1) > >>> root = Tree('zero', trunk='a', branch=1) > >>> print root > ** Tree ** > ('trunk',) : 'a', > () : 'zero', > ('branch',) : 1, > > (3) With items: > >>> root = Tree('zero', trunk='a', branch=1, _node_items={'try' : 'x'}) > >>> print root > ** Tree ** > ('trunk',) : 'a', > () : 'zero', > (('try',),) : 'x', > ('branch',) : 1, > or like this: > >>> root = Tree('value', {'x' : 'v1', 'y' : 2}, trunk='v3', branch=4) > >>> print root > ** Tree ** > ('trunk',) : 'v3', > () : 'value', > (('y',),) : 2, > ('branch',) : 4, > (('x',),) : 'v1', > > The items can be considered as attributes of a Tree node, something like > XML attr? '') > > (4) A more complicated one: > >>> root = Tree('value', {'x' : 'v1', 'y' : Tree(2, {'z' : 'v3'}, br=4)}, > trunk='v5', branch=Tree(6, {'a' : 'v7'}, br=8)) > >>> print root > ** Tree ** > ('branch', ('a',)) : 'v7', > (('y',),) : 2, > ('branch',) : 6, > ('branch', 'br') : 8, > ('trunk',) : 'v5', > (('x',),) : 'v1', > (('y', 'z'),) : 'v3', > () : 'value', > (('y',), 'br') : 4, > > 2. Or create a Tree with setattr syntax : > >>> root = Tree(None) > >>> root = Tree('value') > >>> root['x'] = 'v1' > >>> root['y'] = 2 > >>> root.trunk = 'v5' > >>> root.branch = 6 > >>> root['x']['z'] = 'v3' > >>> root['x'].br = 4 > >>> root.branch['a'] = 'v7' > >>> root.branch.br = 8 > >>> print root > ** Tree ** > ('branch', ('a',)) : 'v7', > () : 'value', > (('y',),) : 2, > ('branch',) : 6, > ('branch', 'br') : 8, > ('trunk',) : 'v5', > (('x', 'z'),) : 'v3', > (('x',),) : 'v1', > (('x',), 'br') : 4, > > 3. It's very simple to retrive the value of any given Tree node: > >>> print root > ** Tree ** > (('x', 'y'),) : 'xy', > (('y',),) : 3, > ('branch',) : 7, > ('trunk', ('a',)) : 5, > ('trunk',) : 4, > (('x',),) : 1, > ('trunk', ('a', 'b'), 'data') : ['trunk', 'ab', 6], > () : 0, > (('x',), 'data') : ['x', 2], > ('trunk', ('a', 'b')) : 'trunk ab', > ('trunk', ('a',), 'data') : 'a data', > ('branch', 'data') : 8, > >>> root() > 0 > >>> root.trunk() > 4 > >>> root.branch() > 7 > >>> root['x'] >> >>> root['x']() > 1 > >>> root['x'].data() > ['x', 2] > > 4. As you have seen, the "print" operation of course have traversed the > Tree. Traverse > return a path sequences to nodes map(dict) -- Tree > dict, every > item represents a single Tree node. It't better to be called by > __call__('traverse'), for example: > root('traverse') will return: > treedict = { > { > () : Tree(0), > (('x',),) : Tree(1), > (('x',), 'data') : Tree(['x', 2]), > (('x', 'y'),) : Tree('xy'), > (('y',),) : Tree(3), > ('trunk',) : Tree(4), > ('trunk', ('a',)) : Tree(5), > ('trunk', ('a',), 'data') : Tree("a data"), > ('trunk', ('a', 'b')) : Tree("trunk ab"), > ('trunk', ('a', 'b'), 'data') : Tree(['trunk', 'ab', 6]), > ('branch',) : Tree(7), > ('branch', 'data') : Tree(8) > } > > 5. Update a Tree with another one: > >>> def build_tree1(): > root['x'] = '1x' > ... root = Tree(0) > root.trunk['a'] = 5 > ... root['x'] = '1x' > root.branch.data.extra = ['extra', 'info'] > ... root['x'].data = 1 > ... root['x']['y'] = '1xy' > ... root['x']['y'].data = 2 > ... root['y'] = 3 > ... root.trunk = 4 > ... root.trunk['a'] = 5 > ... root.trunk['a'].data = '5' > ... root.trunk['x'] = '2x' > ... root.trunk ['x'].data = 6 > ... root.trunk['x']['y'] = '2xy' > ... root.trunk['x']['y'].data = 7 > ... root.branch = 8 > ... root.branch.data = 9 > ... root.branch.data.extra = ['extra', 'info'] > ... return root > ... > >>> def build_tree2(): > root['x'] = '1.x' > ... root = Tree('0') > root.trunk['x'] = ' two.x' > ... root['x'] = '1.x' > root.branch.new = 'attr.new' > return root... root['x'].data = '1' > ... root['new'] = '1.new' > ... root.trunk = '4' > ... root.trunk['a'] = "a test" > ... root.trunk['x'] = None > ... root.trunk['b'] = 'b' > ... root.trunk['x'] = ' two.x' > ... root.trunk['x']['y'] = '2.xy' > ... root.trunk['x']['y'].data = '7' > ... root.trunk['new'] = '2.new' > ... root.trunk['new'].data = ' 2.new.data' > ... root.branch = '8' > ... root.branch.new = 'attr.new' > ... return root > ... > >>> tree1 = build_tree1() > >>> tree2 = build_tree2() > > Then you can update tree1 like these to build a new Tree: > >>> tree1('update', tree2) > >>> print tree1 > ** Tree ** > ('branch', 'data', 'extra') : ['extra', 'info'], > ('branch', 'new') : 'attr.new', > ('trunk', ('x', 'y')) : '2.xy', > ('trunk', ('x',), 'data') : 6, > ('branch',) : '8', > ('trunk', ('x', 'y'), 'data') : '7', > (('x',), 'data') : '1', > ('trunk',) : '4', > ('trunk', ('new',), 'data') : ' 2.new.data', > ('trunk', ('new',)) : '2.new', > ('trunk', ('x',)) : 'two.x', > (('x',),) : '1.x', > ('trunk', ('a',)) : 'a test', > () : '0', > (('y',),) : 3, > (('x', 'y'),) : '1xy', > ('trunk', ('a',), 'data') : '5', > ('trunk', ('b',)) : 'b', > ('branch', 'data') : 9, > (('new',),) : '1.new', > (('x', 'y'), 'data') : 2, > > You can also use "+=" operator to do this: > >>> tree1 = build_tree1() > >>> tree1 += tree2 > >>> print tree1 > ** Tree ** > ('branch', 'data', 'extra') : ['extra', 'info'], > ('branch', 'new') : ' attr.new ', > ('trunk', ('x', 'y')) : '2.xy', > ('trunk', ('x',), 'data') : 6, > ('branch',) : '8', > ('trunk', ('x', 'y'), 'data') : '7', > (('x',), 'data') : '1', > ('trunk',) : '4', > ('trunk', ('new',), 'data') : '2.new.data', > ('trunk', ('new',)) : ' 2.new', > ('trunk', ('x',)) : 'two.x', > (('x',),) : '1.x', > ('trunk', ('a',)) : 'a test', > () : '0', > (('y',),) : 3, > (('x', 'y'),) : '1xy', > ('trunk', ('a',), 'data') : '5', > ('trunk', ('b',)) : 'b', > ('branch', 'data') : 9, > (('new',),) : '1.new', > (('x', 'y'), 'data') : 2, > > Or use "+" to build a new Tree: > >>> tree3 = tree1 + tree2 > > 6. Compare 2 Trees: > Compare the root node value first, and if equal, compare their sub nodes, > attributes or items ... > > 7. Some other functions that have not been implemented ... > > ============ > So far I use this Tree as a direct configuration method. For instance, > in my another project cutils which has a tool to do realtime file system > mirroring, the configuration file is like this: > sh# cat /etc/python/fs_mirror > """ > The configuration file for fs_mirror > """ > > import tree > options = tree.Tree('fs_mirror') > o = options > > #o.mode = 'daemon' > # There can be other mode, such as "run_once" > > #o.host = 'localhost' > #o.port = 2123 > # The server runs mirrord > #o.timeout = 60 > > #o.daemon = None > #o.daemon.datadir = "/var/fs_mirror" > # The mirrored dirs/files will be put into this directory > > #o.fssync = 'Report' > # The synchronization mechanism you choose, it can be one of: > # FTP, NFS, SMB/CIFS, SSH, RSYNC, ... > # REPORT only reports the actions in wmLog, > # does not do actual dirs creating or files transport > ###o.fssync.host = 'localhost' > # Must be the same as o.host? > #o.fssync.port = 0 > #o.fssync.user = 'root' > #o.fssync.passwd = '' > # Since it contains passord, you'd better keep this configuration file > secret. > # You can put the id/password pair to a secret file, such as > # ~/.fs_mirror/secret > # $host:$password > # and use --password-from ~/.fs_mirror/secret:$host > # option of fs_mirror script to appoint the password > # By this way, another user can not view the passwords by run "ps" > # when you appointed the it from the command line option. > # The reason a command line options is used is for multi-mirroring > > And the script read and analyze this configuration file can be written > like this: > ... > CONFIG_MODULE_PATH = "/etc/python" > ... > options = tree.Tree('fs_mirror') > options.mode = 'daemon' > options.host = 'localhost' > options.port = 2123 > options.timeout = 60 > options.daemon = None > options.daemon.datadir = "/var/fs_mirror" > options.fssync = 'Report' > options.fssync.port = 0 > options.fssync.user = 'root' > options.fssync.passwd = '' > > # Update options from a configuration file: > try: > sys.path.insert (0, CONFIG_MODULE_PATH) > try: > import fs_mirror_config as config > options('update', config.options) > except ImportError: > pass > sys.path.pop (0) > except tree.TreeExc, trexc: > strerr = "Invalid option because of: %s" % trexc.msg > print >> sys.stderr, strerr > syslog.syslog(syslog.LOG_ERR, strerr) > sys.exit (1) > > # Update options from command line parameters: > opts, args = getopt.gnu_getopt(sys.argv[1:], 'm:h:p:t:o:v', > ['mode=', 'host=', 'port=', 'timeout=', 'option=', 'datadir=', > 'help', 'verbose', 'password-from=']) > if args: > options.identities = args > ov = [] > for o, v in opts: > if o == '-m' or o == '--mode': > options.mode = v > elif o == '-h' or o == '--host': > options.host = v > elif o == '-p' or o == '--port': > options.port = int(v) > elif o == '-t' or o == '--timeout': > options.timeout = int(v) > elif o == "--datadir": > options.daemon.datadir = v > elif o == '-o' or o == '--option': > ov.append(v) > elif o == '--help': > print usage > sys.exit(0) > elif o == '-v' or o == '--verbose': > fs_mirror.debug = 1 > fs_sync.debug = 1 > elif o == '--password-from': > try: > fname, hostid = v.split(':') > except ValueError: > raise ValueError, "Invalid secret-file:id pair for > --passwd-from" > for line in open(fname, 'r'): > line = line.strip() > try: > id, passwd = line.split(':') > if id == hostid: > options.fssync.passwd = passwd > break > except ValueError: > raise ValueError, "Invalid id:password pair record '%s'" > % line > options('update', oparse(ov)) > > You can find the document of "cutils" project at: > http://crablfs.sourceforge.net /#ru_data_man > and download it from: > http://sourceforge.net/projects/crablfs > > But I think this Tree structure can also be used in other ways. For > example, I think it's possible to implement an API to read XML into such > structure ... > > ============ > Luckily the basic definition has been finished now, you can also download > it from: > http://sourceforge.net/projects/crablfs > the document is in the code and unittest. And I have put the HTML at: > http://crablfs.sourceforge.net/tree.html > > The source code is in SVN: > https://crablfs.svn.sourceforge.net/svnroot/crablfs/caxes/trunk/ > the files are tree.py and test_tree.py. > > I hope this can be useful to you. Maybe I can write a PEP? Looking > forward to your suggestions and advices... > > I'm not so expericenced, and this is only a partial finished work, since > I can only squash my limited spare time to do this and there is several > projects I have started. There are many things to learn, and now I'm > learning from you '') > > Thank you. > > -- > ------------------------------------------------------------------------ > My Projects: > http://sourceforge.net/projects/crablfs > http://crablfs.sourceforge.net/ > http://crablfs.sourceforge.net/#ru_data_man > http://crablfs.sourceforge.net/tree.html > http://cralbfs.sourceforge.net/sysadm_zh_CN.html > My Blog: > http://chowroc.blogspot.com/ > http://hi.baidu.com/chowroc_z/ > Looking for a space and platform to exert my originalities (for my > projects)... > _______________________________________________ > python-chinese > Post: send python-chinese at lists.python.cn > Subscribe: send subscribe to > python-chinese-request at lists.python.cn > Unsubscribe: send unsubscribe to > python-chinese-request at lists.python.cn > Detail Info: > http://python.cn/mailman/listinfo/python-chinese >
2007年11月09日 星期五 15:19
·Ç³£¸ÐлÄãµÄ»Ø¸´ºÍ½¨Òé¡£ ÕâÁ½Ìì´òËãÖØÐÂдһϵ¥Ôª²âÊÔ£¬ÒÔǰдµÄµ¥Ôª²âÊÔʵÔÚÊDZȽÏÔã¸â -_-! ¶øÇÒ¹¤×÷ÉϵÄÊÂÇéÒ²±È½ÏÔÓ£¬ËùÒÔûÓм°Ê±»Ø¸´¡£ ¹ØÓÚÄã˵µÄÕ⼸µã£¬ÎÒ¾õµÃÓм¸µãÎÒ¿ÉÒÔ½øÒ»²½ËµÃ÷µÄ¡£²»¹ýÕâÁ½Ìì±È½Ï棬ÎÒÓÐʱ¼äÕûÀíÒ»ÏÂ˼·°É¡£´óÌåÉÏ£¬ÕâµÄÈ·²»ÊÇÒ»¸öÊý¾Ý½á¹¹É쵀 Tree£¬»òÕß˵²»ÊÇÒ»¸ö´æ´¢µÄÊý¾Ý½á¹¹É쵀 Tree£¬¶ø¸üÏñÊÇÎļþϵͳÄÇÑùµÄ directory Tree£¬ÃæÏò¸üÉϲãµÄʹÓÃÕß°É¡£´æ´¢ÉÏ£¬ÎÒ¾õµÃ¿ÉÒÔÔÙÏë±ðµÄ°ì·¨£¬±ÈÈç Berkeley DB£¬¶ÔÓÚʹÓÃËüµÄÈËÀ´Ëµ£¬Ëü¸üÏñÊÇÒ»¸ö Hash Table£¬µ«Êµ¼ÊÉÏÈ´¿ÉÄÜʹÓÃÁË Hash, BTree »ò Queue À´½øÐÐʵ¼ÊµÄ´æ´¢¡£²»¹ýÈç¹ûÓà BTree µÄ»°£¬Õ¼ÓõĴ洢¿Õ¼ä¾Í»á±È½Ï´ó£¬ÔÚÄÚ´æÖÐËÆºõ²»Ì«ºÏÊÊ¡£ »»Ò»¸ö½Ç¶ÈÀ´¿¼ÂÇ£¬ÎÒ¾õµÃ¿ÉÄܸü½Ó½üÓÚ DOM »ò ElementTree ÕâÑùµÄ¶«Î÷£¬²»¹ýÎÒÏ£Íû¸ü¼òµ¥£¬²»Ï£ÍûÈ¥´¦Àí XML µÄ¸´ÔÓÐÔ£¬²¢ÇÒÏ£ÍûÓиüºÃµÄ¿É¶ÁÐԵȵÈ... ¶øÇÒÎÒ¸öÈ˾õµÃ¸ü Pythonic£¬µ±È»Ã¿¸öÈË¶Ô Pythonic µÄÀí½â¿ÉÄܲ»Ò»Ñù£¬²»¹ýÎÒÏë¼ÈÈ» Python ÌṩÁËÕâÑùµÄÄÜÁ¦£¬ÎªÊ²Ã´²»½«Ëü·¢»Óµ½¼«ÖÂÄØ£¿ Äã¶ÔÓÚ iterator µÄ½¨ÒéºÜÓеÀÀí¡£·Ç³£¸Ðл¡£'') ÓÐʱ¼äÎÒÕûÀíÏÂ˼·Ïêϸ˵Ã÷°É¡£ÎÒ¿ÉÄÜÒ²ÐèҪдÎĵµÁË¡£ On Nov 7, 2007 8:47 AM, swordsp <sparas2006在gmail.com> wrote: > ˳µÀȥȥsfÉÏ¿´ÁËһϣ¬×î´óµÄ¸ÐÏëÊÇÎĵµÕæ°ô£¬Äѵÿ´µ½¹úÈË×öµÄ¿ªÔ´ÏîÄ¿ÄÜÕâô"רҵ":) > > »Øµ½Õâ¸ötreeµÄÄ£¿é£¬Ëµ¼¸µãÎÒµÄÏë·¨£º > > µÚÒ»Ó¡Ïó£¬Õâ´ó¸Å²»ÄÜËãÊÇÒ»¸ö"general > > purpose"µÄtree£¬ÕâÒ»µãºÍÄÚÖõÄlistºÍdict¸Ð¾õ²»Ò»Ñù¡£ÔÚÎÒµÄÀí½âÖУ¬´ÓÊý¾Ý½á¹¹µÄÊÓ½ÇÀ´¿´£¬treeµÄºËÐĸÅÄîÖ»Óнڵ㼰Æä¸¸×Ó¹ØÏµ£¨rootºÍleaf¶¼ÊÇÓɴ˶øÀ´µÄÑÜÉú¸ÅÄ£¬»ù±¾²Ù×÷Ö»ÓнڵãµÄCRUD¡¢±éÀúÒÔ¼°¶ÔÕû¿Å×ÓÊ÷µÄÒÆ¶¯£¬ÆäËüµÄ¶¼²»ÄÜËãÊÇ»ù±¾ÓïÒå¡£ > > > Õâ¸öÄ£¿éÖдóÁ¿Ê¹ÓÃkey-valueµÄÓïÒåÀ´´¦Àí½Úµã£¬¶ÔÓÚµ¥´¿µÄ"tree"À´ËµÆäʵÊÇÔö¼ÓÁ˲»±ØÒªµÄ¸´ÔÓÐÔ¡£ÓÈÆäÊÇÓÐЩµØ·½ÎªÁËapiµÄʹÓñãÀû£¬ÈýӿڵÄÓïÒå±äµÃÄ£ºý£¨attributeºÍitemsÁ½ÖÖ"×Ó½Úµã"µÄ¸ÅÄmulti-keyºÍnested-keyµÄͬʱ֧³Ö£¬½Úµã¸³ÖµÊ±valueºÍsubtreeµÄ´¦Àí£¬¶¼ÊǺÜÈÝÒ×´øÀ´»ìÏýµÄµØ·½£©£¬¸öÈ˾õµÃ¿ÉÄÜÊǵò»³¥Ê§µÄ¡£ > > > ÎÒ¸öÈ˱ȽÏϲ»¶µÄ·½Ê½ÊǰÑÕâЩºËÐĵĸÅÄîÒÔ¼°»ù´¡µÄapi³éÀë³öÀ´×÷Ϊһ¸ö»ùÀ࣬±£³ÖÆä¼ò½àºÍµ¥´¿£¨ÕâÀïÎÒ¾õµÃÓÃÏÔʽµÄ·½·¨ÉùÃ÷»á±ÈÓÃÒþʽµÄaction·ÖÅɸüÇåÎúһЩ£©£¬È»ºóÔÚ²»Í¬Ó¦Óó¡¾°£¨±ÈÈçÕâÀïÊÇÓÃÓÚÅäÖùÜÀí£©ÖÐʹÓò»Í¬À©Õ¹ÊµÏÖÀ´ÌṩһЩ±ãÀûµÄ¸½¼Ó·½·¨¡£ > > > Æäʵ½ö½öÊÇΪÁ˱í´ïÕâÖÖÓвã´ÎµÄÐÅÏ¢µÄ»°£¬Ç¶Ì×list/dict»òÕßpython×Ô¼ºµÄclass´ó¶àÊýʱºòÒѾ¹»ÓÃÁË£¬ÕæÕýÐèÒªtreeµÄʱºò¶à°ëÊÇÓõ½Ä³ÖÖÌØ¶¨µÄ´æ´¢½á¹¹£¨±ÈÈçÆ½ºâÊ÷¡¢BÊ÷¡¢ºìºÚÊ÷µÈµÈ£©À´ÊµÏÖ¸ßЧµÄCRUD²Ù×÷£¬Èç¹ûÒª×÷Ϊ»ù´¡¿âÉè¼ÆµÄ»°£¬Õâ·½Ãæ×îºÃÁôÏÂÀ©Õ¹µÄÓàµØ¡£ÖÁÉÙ£¬traverse·µ»Øiterable»á±ÈÖ±½Ó·µ»ØÒ»¸ödictÒªºÃЩ¡£ > > µ±È»£¬Ä£¿é±¾ÉíÆäʵдµÃºÜƯÁÁ£¬×÷ÕßÓ¦¸ÃÓÐÏ൱µÄ¾Ñ飬ÕâÀïÖ»ÊÇÏë±í´ïһϸöÈ˶ÔapiÉè¼Æ·½ÃæµÄ²»Í¬ÀíÄî¡£ > > _______________________________________________ > python-chinese > Post: send python-chinese在lists.python.cn > Subscribe: send subscribe to python-chinese-request在lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request在lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese -- ------------------------------------------------------------------------ My Projects: http://sourceforge.net/projects/crablfs http://crablfs.sourceforge.net/ http://crablfs.sourceforge.net/#ru_data_man http://crablfs.sourceforge.net/tree.html http://cralbfs.sourceforge.net/sysadm_zh_CN.html My Blog: http://chowroc.blogspot.com/ http://hi.baidu.com/chowroc_z/ Looking for a space and platform to exert my originalities (for my projects)... -------------- 下一部分 -------------- Ò»¸öHTML¸½¼þ±»ÒƳý... URL: http://python.cn/pipermail/python-chinese/attachments/20071109/834a8114/attachment.html
Zeuux © 2025
京ICP备05028076号