zoukankan      html  css  js  c++  java
  • python ConfigParser、shutil、subprocess、ElementTree模块简解

                          ConfigParser 模块

    一、ConfigParser简介
    ConfigParser 是用来读取配置文件的包。配置文件的格式如下:中括号“[ ]”内包含的为section。section 下面为类似于key-value 的配置内容

    [db]
    db_host = 127.0.0.1
    db_port = 22
    db_user = root
    db_pass = rootroot
    [concurrent]
    thread = 10
    processor = 20

    中括号“[ ]”内包含的为section。紧接着section 为类似于key-value 的options 的配置内容。

    二、ConfigParser 初始工作
    使用ConfigParser 首选需要初始化实例,并读取配置文件:

    cf = ConfigParser.ConfigParser()
    cf.read("配置文件名")

    三、ConfigParser 常用方法
    1. 获取所有sections。也就是将配置文件中所有“[ ]”读取到列表中:

    s = cf.sections()
    print 'section:', s

    将输出(以下将均以简介中配置文件为例):

    section: ['db', 'concurrent']

    2. 获取指定section 的options。即将配置文件某个section 内key 读取到列表中:

    o = cf.options("db")
    print 'options:', o

    将输出:

    options: ['db_host', 'db_port', 'db_user', 'db_pass']

    3. 获取指定section 的配置信息。

    v = cf.items("db")
    print 'db:', v

    将输出:

    db: [('db_host', '127.0.0.1'), ('db_port', '22'), ('db_user', 'root'), ('db_pass', 'rootroot')]

    4. 按照类型读取指定section 的option 信息。

    db_host = cf.get("db", "db_host")
    db_port = cf.getint("db", "db_port")
    db_user = cf.get("db", "db_user")
    db_pass = cf.get("db", "db_pass")
    
    # 返回的是整型的
    threads = cf.getint("concurrent", "thread")
    processors = cf.getint("concurrent", "processor")
    print "db_host:", db_host
    print "db_port:", db_port
    print "db_user:", db_user
    print "db_pass:", db_pass
    print "thread:", threads
    print "processor:", processors
    将输出:
    db_host: 127.0.0.1
    db_port: 22
    db_user: root
    db_pass: rootroot
    thread: 10
    processor: 20

    5. 设置某个option 的值。(记得最后要写回)

    cf.set("db", "db_pass", "zhaowei")
    cf.write(open("test.conf", "w"))

    6.添加一个section。(同样要写回)

    cf.add_section('liuqing')
    cf.set('liuqing', 'int', '15')
    cf.set('liuqing', 'bool', 'true')
    cf.set('liuqing', 'float', '3.1415')
    cf.set('liuqing', 'baz', 'fun')
    cf.set('liuqing', 'bar', 'Python')
    cf.set('liuqing', 'foo', '%(bar)s is %(baz)s!')
    cf.write(open("test.conf", "w"))

    7. 移除section 或者option 。(只要进行了修改就要写回的哦)

    cf.remove_option('liuqing','int')
    cf.remove_section('liuqing')
    cf.write(open("test.conf", "w"))

    但是如果配置文件中,parameter选项中含有[],则无法用此模块进行解析。。因此当试用python作为开发语言时,配置文件的格式可以选择符合configparser模块的格式。。。
    下面的配置就无法使用configparser模块. 会将含有[]的部分当作section来解析

    [db]  
    host[0]=127.0.0.1  
    host[1] = 192.168.1.123  
    db_port=3306  
    db_user=root  
    db_pass=password  
    [concurrent]  
    thread=10  
    processor=20  

    使用configparser模块解析配置文件时,发现的问题:

    参数名称的大写全部会转换为小写。

    参数名称不能含有[,]
    如果含有多个名字相同的section时,会以最后一个section为准。
    还是发现了一个问题,如果不同的section中含有相同参数名字的参数,那个上面这个解析将无法判断出参数来自哪个section。
    例如,myslq的配置文件中,client section和mysqld section中都含有socket和port这两个参数。如果用上面的代码,则无法判断哪个dict中的两个socket和port分别来自哪个section。

                          ElementTree 模块

    用 ElementTree 在 Python 中解析 XML
    原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python-with-elementtree/
    译者: TheLover_Z

    当你需要解析和处理 XML 的时候,Python 表现出了它 “batteries included” 的一面。 标准库 中大量可用的模块和工具足以应对 Python 或者是 XML 的新手。

    几个月前在 Python 核心开发者之间发生了一场 有趣的讨论 ,他们讨论了 Python 下可用的 XML 处理工具的优点,还有如何将它们最好的展示给用户看。这篇文章是我本人的拙作,我打算讲讲哪些工具比较好用还有为什么它们好用,当然,这篇文章也可以当作一个如何使用的基础教程来看。

    这篇文章所使用的代码基于 Python 2.7,你稍微改动一下就可以在 Python 3.x 上面使用了。

    应该使用哪个 XML 库?
    Python 有非常非常多的工具来处理 XML。在这个部分我想对 Python 所提供的包进行一个简单的浏览,并且解释为什么 ElementTree 是你最应该用的那一个。

    xml.dom.* 模块 - 是 W3C DOM API 的实现。如果你有处理 DOM API 的需要,那么这个模块适合你。注意:在 xml.dom 包里面有许多模块,注意它们之间的不同。

    xml.sax.* 模块 - 是 SAX API 的实现。这个模块牺牲了便捷性来换取速度和内存占用。SAX 是一个基于事件的 API,这就意味着它可以“在空中”(on the fly)处理庞大数量的的文档,不用完全加载进内存(见注释1)。

    xml.parser.expat - 是一个直接的,低级一点的基于 C 的 expat 的语法分析器(见注释2)。 expat 接口基于事件反馈,有点像 SAX 但又不太像,因为它的接口并不是完全规范于 

    >>> tree.getroot()
    <Element 'doc' at 0x11eb780>
    import xml.etree.cElementTree as ET
    except ImportError:
        import xml.etree.ElementTree as ET

    这是一个让 Python 不同的库使用相同 API 的一个比较常用的办法。还是那句话,你的编译环境和别人的很可能不一样,所以这样做可以防止一些莫名其妙的小问题。注意:从 Python 3.3 开始,你没有必要这么做了,因为 ElementTree 模块会自动寻找可用的 C 库来加快速度。所以只需要 import xml.etree.ElementTree 就可以了。但是在 3.3 正式推出之前,你最好还是使用我上面提供的那段代码。

    将 XML 解析为树的形式
    我们来讲点基础的。XML 是一种分级的数据形式,所以最自然的表示方法是将它表示为一棵树。ET 有两个对象来实现这个目的 - ElementTree 将整个 XML 解析为一棵树, Element 将单个结点解析为树。如果是整个文档级别的操作(比如说读,写,找到一些有趣的元素)通常用 ElementTree 。单个 XML 元素和它的子元素通常用 Element 。下面的例子能说明我刚才啰嗦的一大堆。(见注释5)

    我们用这个 XML 文件来做例子:

    <?xml version="1.0"?>
    <doc>
        <branch name="testing" hash="1cdf045c">
            text,source
        </branch>
        <branch name="release01" hash="f200013e">
            <sub-branch name="subrelease01">
                xml,sgml
            </sub-branch>
        </branch>
        <branch name="invalid">
        </branch>
    </doc>

    让我们加载并且解析这个 XML :

    >>> import xml.etree.cElementTree as ET
    >>> tree = ET.ElementTree(file='doc1.xml')

    然后抓根结点元素:

    >>> tree.getroot()
    <Element 'doc' at 0x11eb780>
    

     和预期一样,root 是一个 Element 元素。我们可以来看看:

    >>> root = tree.getroot()
    >>> root.tag, root.attrib
    ('doc', {})

    看吧,根元素没有任何状态(见注释6)。就像任何 Element 一样,它可以找到自己的子结点:

    >>> for child_of_root in root:
    ...   print child_of_root.tag, child_of_root.attrib
    ...
    branch {'hash': '1cdf045c', 'name': 'testing'}
    branch {'hash': 'f200013e', 'name': 'release01'}
    branch {'name': 'invalid'}
    

    我们也可以进入一个指定的子结点:

    >>> root[0].tag, root[0].text
    ('branch', '
            text,source
        ')
    

    找到我们感兴趣的元素
    从上面的例子我们可以轻而易举的看到,我们可以用一个简单的递归获取 XML 中的任何元素。然而,因为这个操作比较普遍,ET 提供了一些有用的工具来简化操作.

    Element 对象有一个 iter 方法可以对子结点进行深度优先遍历。 ElementTree 对象也有 iter 方法来提供便利。

    >>> for elem in tree.iter():
    ...   print elem.tag, elem.attrib
    ...
    doc {}
    branch {'hash': '1cdf045c', 'name': 'testing'}
    branch {'hash': 'f200013e', 'name': 'release01'}
    sub-branch {'name': 'subrelease01'}
    branch {'name': 'invalid'}
    

     遍历所有的元素,然后检验有没有你想要的。ET 可以让这个过程更便捷。 iter 方法接受一个标签名字,然后只遍历那些有指定标签的元素:

    >>> for elem in tree.iter(tag='branch'):
    ...   print elem.tag, elem.attrib
    ...
    branch {'hash': '1cdf045c', 'name': 'testing'}
    branch {'hash': 'f200013e', 'name': 'release01'}
    branch {'name': 'invalid'}

    为了寻找我们感兴趣的元素,一个更加有效的办法是使用 XPath 支持。 Element 有一些关于寻找的方法可以接受 XPath 作为参数。 find 返回第一个匹配的子元素, findall 以列表的形式返回所有匹配的子元素, iterfind 为所有匹配项提供迭代器。这些方法在 ElementTree 里面也有。
    给出一个例子:

    >>> for elem in tree.iterfind('branch/sub-branch'):
    ...   print elem.tag, elem.attrib
    ...
    sub-branch {'name': 'subrelease01'}
    

    这个例子在 branch 下面找到所有标签为 sub-branch 的元素。然后给出如何找到所有的 branch 元素,用一个指定 name 的状态即可:

    >>> for elem in tree.iterfind('branch[@name="release01"]'):
    ...   print elem.tag, elem.attrib
    ...
    branch {'hash': 'f200013e', 'name': 'release01'}

    建立 XML 文档
    ET 提供了建立 XML 文档和写入文件的便捷方式。 ElementTree 对象提供了 write 方法。
    现在,这儿有两个常用的写 XML 文档的脚本。
    修改文档可以使用 Element 对象的方法:

    >>> root = tree.getroot()
    >>> del root[2]
    >>> root[0].set('foo', 'bar')
    >>> for subelem in root:
    ...   print subelem.tag, subelem.attrib
    ...
    branch {'foo': 'bar', 'hash': '1cdf045c', 'name': 'testing'}
    branch {'hash': 'f200013e', 'name': 'release01'}
    

     我们在这里删除了根元素的第三个子结点,然后为第一个子结点增加新状态。然后这个树可以写回到文件中。

    >>> import sys
    >>> tree.write(sys.stdout)   # ET.dump can also serve this purpose
    <doc>
        <branch foo="bar" hash="1cdf045c" name="testing">
            text,source
        </branch>
    <branch hash="f200013e" name="release01">
        <sub-branch name="subrelease01">
            xml,sgml
        </sub-branch>
    </branch>
    </doc>

    注意状态的顺序和原文档的顺序不太一样。这是因为 ET 讲状态保存在无序的字典中。语义上来说,XML 并不关心顺序。
    建立一个全新的元素也很容易。ET 模块提供了 SubElement 函数来简化过程:

    >>> a = ET.Element('elem')
    >>> c = ET.SubElement(a, 'child1')
    >>> c.text = "some text"
    >>> d = ET.SubElement(a, 'child2')
    >>> b = ET.Element('elem_b')
    >>> root = ET.Element('root')
    >>> root.extend((a, b))
    >>> tree = ET.ElementTree(root)
    >>> tree.write(sys.stdout)
    <root><elem><child1>some text</child1><child2 /></elem><elem_b /></root>
    

    结论
    在 Python 众多处理 XML 的模块中, ElementTree 真是屌爆了。它将轻量,符合 Python 哲学的 API ,出色的性能完美的结合在了一起。所以说如果要处理 XML ,果断地使用它吧!

                                 shutil 模块
    参数简解:
    shutil.copyfile( src, dst) 从源src复制到dst中去。当然前提是目标地址是具备可写权限。抛出的异常信息为IOException. 如果当前的dst已存在的话就会被覆盖掉
    shutil.move( src, dst) 移动文件或重命名
    shutil.copymode( src, dst) 只是会复制其权限其他的东西是不会被复制的
    shutil.copystat( src, dst) 复制权限、最后访问时间、最后修改时间
    shutil.copy( src, dst) 复制一个文件到一个文件或一个目录
    shutil.copy2( src, dst) 在copy上的基础上再复制文件最后访问时间与修改时间也复制过来了,类似于cp –p的东西
    shutil.copy2( src, dst) 如果两个位置的文件系统是一样的话相当于是rename操作,只是改名;如果是不在相同的文件系统的话就是做move操作
    shutil.copytree( olddir, newdir, True/Flase)
    把olddir拷贝一份newdir,如果第3个参数是True,则复制目录时将保持文件夹下的符号连接,如果第3个参数是False,则将在复制的目录下生成物理副本来替代符号连接
    shutil.rmtree( src ) 递归删除一个目录以及目录内的所有内容

                                  subprocess模块

    从Python 2.4开始,Python引入subprocess模块来管理子进程,以取代一些旧模块的方法:如 os.system、os.spawn*、os.popen*、popen2.*、commands.*不但可以调用外部的命令作为子进程,而且可以连接到子进程的input/output/error管道,获取相关的返回信息
    一、subprocess以及常用的封装函数
    运行python的时候,我们都是在创建并运行一个进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。
    subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

    subprocess.call()
    父进程等待子进程完成
    返回退出信息(returncode,相当于Linux exit code)

    subprocess.check_call()
    父进程等待子进程完成
    返回0
    检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性,可用try…except…来检查

    subprocess.check_output()
    父进程等待子进程完成
    返回子进程向标准输出的输出结果
    检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性和output属性,output属性为标准输出的输出结果,可用try…except…来检查。

    这三个函数的使用方法相类似,下面来以subprocess.call()举例说明:

    >>> import subprocess
    >>> retcode = subprocess.call(["ls", "-l"])
    #和shell中命令ls -a显示结果一样
    >>> print retcode
    0

    将程序名(ls)和所带的参数(-l)一起放在一个表中传递给subprocess.call()
    shell默认为False,在Linux下,shell=False时, Popen调用os.execvp()执行args指定的程序;shell=True时,如果args是字符串,Popen直接调用系统的Shell来执行args指定的程序,如果args是一个序列,则args的第一项是定义程序命令字符串,其它项是调用系统Shell时的附加参数。
    上面例子也可以写成如下:

    >>> retcode = subprocess.call("ls -l",shell=True)
    

    subprocess.Popen()

    class Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
    

    实际上,上面的几个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。
    与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block),举例:

    >>> import subprocess
    >>> child = subprocess.Popen(['ping','-c','4','blog.linuxeye.com'])
    >>> print 'parent process'
    

    从运行结果中看到,父进程在开启子进程之后并没有等待child的完成,而是直接运行print。
    对比等待的情况:

    >>> import subprocess
    >>> child = subprocess.Popen('ping -c4 blog.linuxeye.com',shell=True)
    >>> child.wait()
    >>> print 'parent process'
    

    从运行结果中看到,父进程在开启子进程之后并等待child的完成后,再运行print。
    此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:

    child.poll() # 检查子进程状态
    child.kill() # 终止子进程
    child.send_signal() # 向子进程发送信号
    child.terminate() # 终止子进程
    

    子进程的PID存储在child.pid
    二、子进程的文本流控制
    子进程的标准输入、标准输出和标准错误如下属性分别表示:

    child.stdin
    child.stdout
    child.stderr
    

    可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe),如下2个例子:

    >>> import subprocess
    >>> child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
    >>> print child1.stdout.read(),
    

    或者child1.communicate()

    >>> import subprocess
    >>> child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE)
    >>> child2 = subprocess.Popen(["grep","0:0"],stdin=child1.stdout, stdout=subprocess.PIPE)
    >>> out = child2.communicate()
    

    subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
    注意:communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成

    引自   http://www.jb51.net/article/48086.htm

     

      

     

      

      

     

  • 相关阅读:
    PDOStatement::closeCursor
    PDOStatement::bindValue
    oracle drop table recyclebin恢复
    mysql基准测试工具tpcc-mysql安装、使用、结果解读
    MySQL字符集 GBK、GB2312、UTF8区别 解决 MYSQL中文乱码问题 收藏 MySQL中涉及的几个字符集
    [MySQL FAQ]系列 — EXPLAIN结果中哪些信息要引起关注
    [MySQL优化案例]系列 — 优化InnoDB表BLOB列的存储效率
    数据库专业词语
    老叶观点:MySQL开发规范之我见
    [MySQL FAQ]系列 — 为什么InnoDB表要建议用自增列做主键
  • 原文地址:https://www.cnblogs.com/panwenbin-logs/p/5601644.html
Copyright © 2011-2022 走看看