Python系列之模块、和字符串格式化

python

Python 模块

模块让你能够有逻辑地组织你的Python代码段。

把相关的代码分配到一个 模块里能让你的代码更好用,更易懂。

模块也是Python对象,具有随机的名字属性用来绑定或引用。

模块分为三种:

  • 自定义模块 :自己编写的模块通过
  • 内置模块 :又称为标准库,安装Python之后自带的模块
  • 开源模块:别人写的模块,需要安装之后才可以使用

模块的导入方法:

import module            #适用与内置模块或使用模块的代码文件(A)与模块文件(B)在同一个目录

from xxx.xxx.xxx.module import xx        #适用于模块在别的目录下,在导入时使用 . (点)作为目录的分割

from xxx.xxx.xxx,module import xx as rename #适用于所需要调用的模块比较长或者难记,这个办法是给模块起一个别名

from xxx.xxx.xxx.module import *         #适用于把目录下的所有模块都导入

导入模块其实就是告诉Python解释器去解释那个py文件

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 __init__.py 文件

sys.path添加目录

如果sys.path路径列表没有你想要的路径,可以通过 sys.path.append('路径') 添加。
通过os模块可以获取各种目录;

 内置模块

1、os模块,提供系统级别的操作

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径

os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd

os.curdir 返回当前目录: ('.')

os.pardir 获取当前目录的父目录字符串名:('..')

os.makedirs('dirname1/dirname2') 可生成多层递归目录

os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推

os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname

os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname

os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印

os.remove() 删除一个文件

os.rename("oldname","newname") 重命名文件/目录

os.stat('path/filename') 获取文件/目录信息

os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"

os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"

os.pathsep 输出用于分割文件路径的字符串

os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'

os.system("bash command") 运行shell命令,直接显示

os.environ 获取系统环境变量

os.path.abspath(path) 返回path规范化的绝对路径

os.path.split(path) 将path分割成目录和文件名二元组返回

os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素

os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素

os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False

os.path.isabs(path) 如果path是绝对路径,返回True

os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False

os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False

os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略

os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间

os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

View Code

 2、sys模块,用于提供对解释器相关的操作

sys.argv: 实现从程序外部向程序传递参数。

sys.exit([arg]): 程序中间的退出,arg=0为正常退出。

sys.getdefaultencoding(): 获取系统当前编码,一般默认为ascii。

sys.setdefaultencoding(): 设置系统默认编码,执行dir(sys)时不会看到这个方法,在解释器中执行不通过,可以先执行reload(sys),在执行 setdefaultencoding('utf8'),此时将系统默认编码设置为utf8。(见设置系统默认编码 )

sys.getfilesystemencoding(): 获取文件系统使用编码方式,Windows下返回'mbcs',mac下返回'utf-8'.

sys.path: 获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到。

sys.platform: 获取当前系统平台。

sys.stdin,sys.stdout,sys.stderr stdin , stdout , 以及stderr 变量包含与标准I/O 流对应的流对象. 如果需要更好地控制输出,而print 不能满足你的要求, 它们就是你所需要的. 你也可以替换它们, 这时候你就可以重定向输出和输入到其它设备( device ), 或者以非标准的方式处理它们

sys Code

3、time模块,提供系统时间的操作

print(time.time())  #返回当前系统时间戳

print(time.ctime()) #Thu May 19 18:14:45 2016 当前系统时间

print(time.ctime(time.time())) # 将时间戳转换为字符串格式时间-->Thu May 19 18:16:18 2016

print(time.gmtime()) #打印struct_time格式时间

print(time.localtime()) #以struct_time格式显示本地时间

print(time.mktime(time.gmtime())) #将struct_time格式时间转换为时间戳格式

print(time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime())) #将struct_time格式转换为指定格式

print(time.strptime('2016-05-19','%Y-%m-%d')) # 将字符串格式转换为struct_time格式

time Code

4、datetime模块,提供date与time的结合体包括date与time的所有信息

print(datetime.date.today()) #输出格式2016-05-21

print(datetime.date.fromtimestamp(time.time() - 86400)) #将时间戳转换成日期格式 86400代表一天

cur_time = datetime.datetime.now()

print(cur_time) #2016-05-21 20:06:38.319101

print(cur_time.timetuple()) #返回struct_time 格式

print(cur_time.replace(2016,5,12)) #2016-05-12 20:07:53.104379

datetime Code

5、hashlib 模块

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib

# ######## md5 ########

hash = hashlib.md5()

# help(hash.update)

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

print(hash.digest())

######## sha1 ########

hash = hashlib.sha1()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

# ######## sha256 ########

hash = hashlib.sha256()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

# ######## sha384 ########

hash = hashlib.sha384()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

# ######## sha512 ########

hash = hashlib.sha512()

hash.update(bytes('admin', encoding='utf-8'))

print(hash.hexdigest())

View Code

使用new()创建指定加密模式的hash对象

new(name, string='')

"""

Return a new hashing object using the named algorithm;

optionally initialized with a string.

"""

h = hashlib.new('md5')

print h #<md5 HASH object @ 000000000260BDB0>

h2 = hashlib.new('ripemd160','what')

print h2 #<ripemd160 HASH object @ 000000000271B9F0>

h.update('beginman')

print h.hexdigest() #666fc5baa93a7fb207c5bfff03b67732

#等效

s = hashlib.md5()

s.update('beginman')

print s.hexdigest() #666fc5baa93a7fb207c5bfff03b67732

print h2.hexdigest() #9c1185a5c5e9fc54612808977ee8f548b2258d31

常用属性:

#属性

print hashlib.algorithms #('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') 列出所有加密算法

print h.digest_size #16 产生的散列的字节大小。

print h.block_size #64 The internal block size of the hash algorithm in bytes.

常用方法:

hash.update(arg) #更新哈希对象以字符串参数,如果同一个hash对象重复调用该方法,则m.update(a); m.update(b) is equivalent to m.update(a+b).

hash.digest()#返回摘要,作为二进制数据字符串值,

hash.hexdigest()#返回摘要,作为十六进制数据字符串值,

hash.copy() #复制

6、xml 

XML是实现不同语言或程序之间进行数据交换的协议,XML文件格式如下:

<?xml version="1.0"?>

<data>

<country name="Liechtenstein">

<rank>1</rank>

<year>2008</year>

<gdppc>141100</gdppc>

<neighbor name="Austria" direction="E"/>

<neighbor name="Switzerland" direction="W"/>

</country>

<country name="Singapore">

<rank>4</rank>

<year>2011</year>

<gdppc>59900</gdppc>

<neighbor name="Malaysia" direction="N"/>

</country>

<country name="Panama">

<rank>68</rank>

<year>2011</year>

<gdppc>13600</gdppc>

<neighbor name="Costa Rica" direction="W"/>

<neighbor name="Colombia" direction="E"/>

</country>

</data>

 1、解析XML 

from xml.etree import ElementTree as ET

# 打开文件,读取XML内容

str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点

root = ET.XML(str_xml)

利用ElementTree.XML将字符串解析成xml对象

from xml.etree import ElementTree as ET

# 直接解析xml文件

tree = ET.parse("xo.xml")

# 获取xml文件的根节点

root = tree.getroot()

利用ElementTree.parse将文件直接解析成xml对象

利用ElementTree.parse解析文件

 2、操作XML

 XML格式类型是节点嵌套节点,对于每一个节点均有以下功能,以便对当前节点进行操作:

class Element:

"""An XML element.

This class is the reference implementation of the Element interface.

An element's length is its number of subelements. That means if you

want to check if an element is truly empty, you should check BOTH

its length AND its text attribute.

The element tag, attribute names, and attribute values can be either

bytes or strings.

*tag* is the element name. *attrib* is an optional dictionary containing

element attributes. *extra* are additional element attributes given as

keyword arguments.

Example form:

<tag attrib>text<child/>...</tag>tail

"""

当前节点的标签名

tag = None

"""The element's name."""

当前节点的属性

attrib = None

"""Dictionary of the element's attributes."""

当前节点的内容

text = None

"""

Text before first subelement. This is either a string or the value None.

Note that if there is no text, this attribute may be either

None or the empty string, depending on the parser.

"""

tail = None

"""

Text after this element's end tag, but before the next sibling element's

start tag. This is either a string or the value None. Note that if there

was no text, this attribute may be either None or an empty string,

depending on the parser.

"""

def __init__(self, tag, attrib={}, **extra):

if not isinstance(attrib, dict):

raise TypeError("attrib must be dict, not %s" % (

attrib.__class__.__name__,))

attrib = attrib.copy()

attrib.update(extra)

self.tag = tag

self.attrib = attrib

self._children = []

def __repr__(self):

return "<%s %r at %#x>" % (self.__class__.__name__, self.tag, id(self))

def makeelement(self, tag, attrib):

创建一个新节点

"""Create a new element with the same type.

*tag* is a string containing the element name.

*attrib* is a dictionary containing the element attributes.

Do not call this method, use the SubElement factory function instead.

"""

return self.__class__(tag, attrib)

def copy(self):

"""Return copy of current element.

This creates a shallow copy. Subelements will be shared with the

original tree.

"""

elem = self.makeelement(self.tag, self.attrib)

elem.text = self.text

elem.tail = self.tail

elem[:] = self

return elem

def __len__(self):

return len(self._children)

def __bool__(self):

warnings.warn(

"The behavior of this method will change in future versions. "

"Use specific 'len(elem)' or 'elem is not None' test instead.",

FutureWarning, stacklevel=2

)

return len(self._children) != 0 # emulate old behaviour, for now

def __getitem__(self, index):

return self._children[index]

def __setitem__(self, index, element):

# if isinstance(index, slice):

# for elt in element:

# assert iselement(elt)

# else:

# assert iselement(element)

self._children[index] = element

def __delitem__(self, index):

del self._children[index]

def append(self, subelement):

为当前节点追加一个子节点

"""Add *subelement* to the end of this element.

The new element will appear in document order after the last existing

subelement (or directly after the text, if it's the first subelement),

but before the end tag for this element.

"""

self._assert_is_element(subelement)

self._children.append(subelement)

def extend(self, elements):

为当前节点扩展 n 个子节点

"""Append subelements from a sequence.

*elements* is a sequence with zero or more elements.

"""

for element in elements:

self._assert_is_element(element)

self._children.extend(elements)

def insert(self, index, subelement):

在当前节点的子节点中插入某个节点,即:为当前节点创建子节点,然后插入指定位置

"""Insert *subelement* at position *index*."""

self._assert_is_element(subelement)

self._children.insert(index, subelement)

def _assert_is_element(self, e):

# Need to refer to the actual Python implementation, not the

# shadowing C implementation.

if not isinstance(e, _Element_Py):

raise TypeError('expected an Element, not %s' % type(e).__name__)

def remove(self, subelement):

在当前节点在子节点中删除某个节点

"""Remove matching subelement.

Unlike the find methods, this method compares elements based on

identity, NOT ON tag value or contents. To remove subelements by

other means, the easiest way is to use a list comprehension to

select what elements to keep, and then use slice assignment to update

the parent element.

ValueError is raised if a matching element could not be found.

"""

# assert iselement(element)

self._children.remove(subelement)

def getchildren(self):

获取所有的子节点(废弃)

"""(Deprecated) Return all subelements.

Elements are returned in document order.

"""

warnings.warn(

"This method will be removed in future versions. "

"Use 'list(elem)' or iteration over elem instead.",

DeprecationWarning, stacklevel=2

)

return self._children

def find(self, path, namespaces=None):

获取第一个寻找到的子节点

"""Find first matching element by tag name or path.

*path* is a string having either an element tag or an XPath,

*namespaces* is an optional mapping from namespace prefix to full name.

Return the first matching element, or None if no element was found.

"""

return ElementPath.find(self, path, namespaces)

def findtext(self, path, default=None, namespaces=None):

获取第一个寻找到的子节点的内容

"""Find text for first matching element by tag name or path.

*path* is a string having either an element tag or an XPath,

*default* is the value to return if the element was not found,

*namespaces* is an optional mapping from namespace prefix to full name.

Return text content of first matching element, or default value if

none was found. Note that if an element is found having no text

content, the empty string is returned.

"""

return ElementPath.findtext(self, path, default, namespaces)

def findall(self, path, namespaces=None):

获取所有的子节点

"""Find all matching subelements by tag name or path.

*path* is a string having either an element tag or an XPath,

*namespaces* is an optional mapping from namespace prefix to full name.

Returns list containing all matching elements in document order.

"""

return ElementPath.findall(self, path, namespaces)

def iterfind(self, path, namespaces=None):

获取所有指定的节点,并创建一个迭代器(可以被for循环)

"""Find all matching subelements by tag name or path.

*path* is a string having either an element tag or an XPath,

*namespaces* is an optional mapping from namespace prefix to full name.

Return an iterable yielding all matching elements in document order.

"""

return ElementPath.iterfind(self, path, namespaces)

def clear(self):

清空节点

"""Reset element.

This function removes all subelements, clears all attributes, and sets

the text and tail attributes to None.

"""

self.attrib.clear()

self._children = []

self.text = self.tail = None

def get(self, key, default=None):

获取当前节点的属性值

"""Get element attribute.

Equivalent to attrib.get, but some implementations may handle this a

bit more efficiently. *key* is what attribute to look for, and

*default* is what to return if the attribute was not found.

Returns a string containing the attribute value, or the default if

attribute was not found.

"""

return self.attrib.get(key, default)

def set(self, key, value):

为当前节点设置属性值

"""Set element attribute.

Equivalent to attrib[key] = value, but some implementations may handle

this a bit more efficiently. *key* is what attribute to set, and

*value* is the attribute value to set it to.

"""

self.attrib[key] = value

def keys(self):

获取当前节点的所有属性的 key

"""Get list of attribute names.

Names are returned in an arbitrary order, just like an ordinary

Python dict. Equivalent to attrib.keys()

"""

return self.attrib.keys()

def items(self):

获取当前节点的所有属性值,每个属性都是一个键值对

"""Get element attributes as a sequence.

The attributes are returned in arbitrary order. Equivalent to

attrib.items().

Return a list of (name, value) tuples.

"""

return self.attrib.items()

def iter(self, tag=None):

在当前节点的子孙中根据节点名称寻找所有指定的节点,并返回一个迭代器(可以被for循环)。

"""Create tree iterator.

The iterator loops over the element and all subelements in document

order, returning all elements with a matching tag.

If the tree structure is modified during iteration, new or removed

elements may or may not be included. To get a stable set, use the

list() function on the iterator, and loop over the resulting list.

*tag* is what tags to look for (default is to return all elements)

Return an iterator containing all the matching elements.

"""

if tag == "*":

tag = None

if tag is None or self.tag == tag:

yield self

for e in self._children:

yield from e.iter(tag)

# compatibility

def getiterator(self, tag=None):

# Change for a DeprecationWarning in 1.4

warnings.warn(

"This method will be removed in future versions. "

"Use 'elem.iter()' or 'list(elem.iter())' instead.",

PendingDeprecationWarning, stacklevel=2

)

return list(self.iter(tag))

def itertext(self):

在当前节点的子孙中根据节点名称寻找所有指定的节点的内容,并返回一个迭代器(可以被for循环)。

"""Create text iterator.

The iterator loops over the element and all subelements in document

order, returning all inner text.

"""

tag = self.tag

if not isinstance(tag, str) and tag is not None:

return

if self.text:

yield self.text

for e in self:

yield from e.itertext()

if e.tail:

yield e.tail

节点功能一览表

View Code

由于 每个节点 都具有以上的方法,并且在上一步骤中解析时均得到了root(xml文件的根节点),so   可以利用以上方法进行操作xml文件。

a. 遍历XML文档的所有内容

from xml.etree import ElementTree as ET

############ 解析方式一 ############

"""

# 打开文件,读取XML内容

str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点

root = ET.XML(str_xml)

"""

############ 解析方式二 ############

# 直接解析xml文件

tree = ET.parse("xo.xml")

# 获取xml文件的根节点

root = tree.getroot()

### 操作

# 顶层标签

print(root.tag)

# 遍历XML文档的第二层

for child in root:

# 第二层节点的标签名称和标签属性

print(child.tag, child.attrib)

# 遍历XML文档的第三层

for i in child:

# 第二层节点的标签名称和内容

print(i.tag,i.text)

View Code

b、遍历XML中指定的节点

from xml.etree import ElementTree as ET

############ 解析方式一 ############

"""

# 打开文件,读取XML内容

str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点

root = ET.XML(str_xml)

"""

############ 解析方式二 ############

# 直接解析xml文件

tree = ET.parse("xo.xml")

# 获取xml文件的根节点

root = tree.getroot()

### 操作

# 顶层标签

print(root.tag)

# 遍历XML中所有的year节点

for node in root.iter('year'):

# 节点的标签名称和内容

print(node.tag, node.text)

View Code

c、修改节点内容

由于修改的节点时,均是在内存中进行,其不会影响文件中的内容。所以,如果想要修改,则需要重新将内存中的内容写到文件

from xml.etree import ElementTree as ET

############ 解析方式一 ############

# 打开文件,读取XML内容

str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点

root = ET.XML(str_xml)

############ 操作 ############

# 顶层标签

print(root.tag)

# 循环所有的year节点

for node in root.iter('year'):

# 将year节点中的内容自增一

new_year = int(node.text) + 1

node.text = str(new_year)

# 设置属性

node.set('name', 'alex')

node.set('age', '18')

# 删除属性

del node.attrib['name']

############ 保存文件 ############

tree = ET.ElementTree(root)

tree.write("newnew.xml", encoding='utf-8')

解析字符串方式,修改,保存

View Code

from xml.etree import ElementTree as ET

############ 解析方式二 ############

# 直接解析xml文件

tree = ET.parse("xo.xml")

# 获取xml文件的根节点

root = tree.getroot()

############ 操作 ############

# 顶层标签

print(root.tag)

# 循环所有的year节点

for node in root.iter('year'):

# 将year节点中的内容自增一

new_year = int(node.text) + 1

node.text = str(new_year)

# 设置属性

node.set('name', 'alex')

node.set('age', '18')

# 删除属性

del node.attrib['name']

############ 保存文件 ############

tree.write("newnew.xml", encoding='utf-8')

解析文件方式,修改,保存

解析文件方式,修改,保存

d、删除节点

from xml.etree import ElementTree as ET

############ 解析字符串方式打开 ############

# 打开文件,读取XML内容

str_xml = open('xo.xml', 'r').read()

# 将字符串解析成xml特殊对象,root代指xml文件的根节点

root = ET.XML(str_xml)

############ 操作 ############

# 顶层标签

print(root.tag)

# 遍历data下的所有country节点

for country in root.findall('country'):

# 获取每一个country节点下rank节点的内容

rank = int(country.find('rank').text)

if rank > 50:

# 删除指定country节点

root.remove(country)

############ 保存文件 ############

tree = ET.ElementTree(root)

tree.write("newnew.xml", encoding='utf-8')

解析字符串方式打开,删除,保存

解析字符串方式打开,删除,保存

from xml.etree import ElementTree as ET

############ 解析文件方式 ############

# 直接解析xml文件

tree = ET.parse("xo.xml")

# 获取xml文件的根节点

root = tree.getroot()

############ 操作 ############

# 顶层标签

print(root.tag)

# 遍历data下的所有country节点

for country in root.findall('country'):

# 获取每一个country节点下rank节点的内容

rank = int(country.find('rank').text)

if rank > 50:

# 删除指定country节点

root.remove(country)

############ 保存文件 ############

tree.write("newnew.xml", encoding='utf-8')

解析文件方式打开,删除,保存

解析文件方式打开,删除,保存

3、创建XML文档

from xml.etree import ElementTree as ET

# 创建根节点

root = ET.Element("famliy")

# 创建节点大儿子

son1 = ET.Element('son', {'name': '儿1'})

# 创建小儿子

son2 = ET.Element('son', {"name": '儿2'})

# 在大儿子中创建两个孙子

grandson1 = ET.Element('grandson', {'name': '儿11'})

grandson2 = ET.Element('grandson', {'name': '儿12'})

son1.append(grandson1)

son1.append(grandson2)

# 把儿子添加到根节点中

root.append(son1)

root.append(son1)

tree = ET.ElementTree(root)

tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

创建方式(一)

创建方式一

from xml.etree import ElementTree as ET

# 创建根节点

root = ET.Element("famliy")

# 创建大儿子

# son1 = ET.Element('son', {'name': '儿1'})

son1 = root.makeelement('son', {'name': '儿1'})

# 创建小儿子

# son2 = ET.Element('son', {"name": '儿2'})

son2 = root.makeelement('son', {"name": '儿2'})

# 在大儿子中创建两个孙子

# grandson1 = ET.Element('grandson', {'name': '儿11'})

grandson1 = son1.makeelement('grandson', {'name': '儿11'})

# grandson2 = ET.Element('grandson', {'name': '儿12'})

grandson2 = son1.makeelement('grandson', {'name': '儿12'})

son1.append(grandson1)

son1.append(grandson2)

# 把儿子添加到根节点中

root.append(son1)

root.append(son1)

tree = ET.ElementTree(root)

tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

创建方式(二)

创建方式二

from xml.etree import ElementTree as ET

# 创建根节点

root = ET.Element("famliy")

# 创建节点大儿子

son1 = ET.SubElement(root, "son", attrib={'name': '儿1'})

# 创建小儿子

son2 = ET.SubElement(root, "son", attrib={"name": "儿2"})

# 在大儿子中创建一个孙子

grandson1 = ET.SubElement(son1, "age", attrib={'name': '儿11'})

grandson1.text = '孙子'

et = ET.ElementTree(root) #生成文档对象

et.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)

创建方式(三)

创建方式三

由于原生保存的XML时默认无缩进,如果想要设置缩进的话, 需要修改保存方式:

from xml.etree import ElementTree as ET

from xml.dom import minidom

def prettify(elem):

"""将节点转换成字符串,并添加缩进。

"""

rough_string = ET.tostring(elem, 'utf-8')

reparsed = minidom.parseString(rough_string)

return reparsed.toprettyxml(indent="\t")

# 创建根节点

root = ET.Element("famliy")

# 创建大儿子

# son1 = ET.Element('son', {'name': '儿1'})

son1 = root.makeelement('son', {'name': '儿1'})

# 创建小儿子

# son2 = ET.Element('son', {"name": '儿2'})

son2 = root.makeelement('son', {"name": '儿2'})

# 在大儿子中创建两个孙子

# grandson1 = ET.Element('grandson', {'name': '儿11'})

grandson1 = son1.makeelement('grandson', {'name': '儿11'})

# grandson2 = ET.Element('grandson', {'name': '儿12'})

grandson2 = son1.makeelement('grandson', {'name': '儿12'})

son1.append(grandson1)

son1.append(grandson2)

# 把儿子添加到根节点中

root.append(son1)

root.append(son1)

raw_str = prettify(root)

f = open("xxxoo.xml",'w',encoding='utf-8')

f.write(raw_str)

f.close()

View Code

7、requests

Python标准库中提供了:urllib等模块以供Http请求,但是,它的 API 太渣了。它是为另一个时代、另一个互联网所创建的。它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务。

import urllib.request

f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')

result = f.read().decode('utf-8')

View Code

import urllib.request

req = urllib.request.Request('http://www.example.com/')

req.add_header('Referer', 'http://www.python.org/')

r = urllib.request.urlopen(req)

result = f.read().decode('utf-8')

发送携带请求头的GET请求

带请求头的GET请求

注:更多见Python官方文档:https://docs.python.org/3.5/library/urllib.request.html#module-urllib.request

Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,从而使得Pythoner进行网络请求时,变得美好了许多,使用Requests可以轻而易举的完成浏览器可有的任何操作。

1、安装模块

pip3 install requests

2、使用模块

# 1、无参数实例

import requests

ret = requests.get('https://github.com/timeline.json')

print(ret.url)

print(ret.text)

# 2、有参数实例

import requests

payload = {'key1': 'value1', 'key2': 'value2'}

ret = requests.get("http://httpbin.org/get", params=payload)

print(ret.url)

print(ret.text)

GET请求

GET请求

# 1、基本POST实例

import requests

payload = {'key1': 'value1', 'key2': 'value2'}

ret = requests.post("http://httpbin.org/post", data=payload)

print(ret.text)

# 2、发送请求头和数据实例

import requests

import json

url = 'https://api.github.com/some/endpoint'

payload = {'some': 'data'}

headers = {'content-type': 'application/json'}

ret = requests.post(url, data=json.dumps(payload), headers=headers)

print(ret.text)

print(ret.cookies)

POST请求

requests.get(url, params=None, **kwargs)

requests.post(url, data=None, json=None, **kwargs)

requests.put(url, data=None, **kwargs)

requests.head(url, **kwargs)

requests.delete(url, **kwargs)

requests.patch(url, data=None, **kwargs)

requests.options(url, **kwargs)

# 以上方法均是在此方法的基础上构建

requests.request(method, url, **kwargs)

其他请求

其他请求

更多requests模块相关的文档见:http://cn.python-requests.org/zh_CN/latest/

3、Http请求和XML实例

实例:检测QQ账号是否在线

import urllib

import requests

from xml.etree import ElementTree as ET

# 使用内置模块urllib发送HTTP请求,或者XML格式内容

"""

f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')

result = f.read().decode('utf-8')

"""

# 使用第三方模块requests发送HTTP请求,或者XML格式内容

r = requests.get('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508')

result = r.text

# 解析XML格式内容

node = ET.XML(result)

# 获取内容

if node.text == "Y":

print("在线")

else:

print("离线")

检测QQ是否在线

实例:查看火车停靠信息

import urllib

import requests

from xml.etree import ElementTree as ET

# 使用内置模块urllib发送HTTP请求,或者XML格式内容

"""

f = urllib.request.urlopen('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=')

result = f.read().decode('utf-8')

"""

# 使用第三方模块requests发送HTTP请求,或者XML格式内容

r = requests.get('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=')

result = r.text

# 解析XML格式内容

root = ET.XML(result)

for node in root.iter('TrainDetailInfo'):

print(node.find('TrainStation').text,node.find('StartTime').text,node.tag,node.attrib)

火车停靠信息

8、logging 

logging 专门用来打印日志, 其实就是各种写数据流的封装. 由于扩展性好且线程安全的, 设置灵活所以使用比较广泛.从一个使用场景开始

开发一个日志系统, 既要把日志输出到控制台, 还要写入日志文件

单文件操作:

import logging

logging.basicConfig(filename='log.log',

format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',

datefmt='%Y-%m-%d %H:%M:%S %p',

level=10)

logging.debug('debug')

logging.info('info')

logging.warning('warning')

logging.error('error')

logging.critical('critical')

logging.log(10,'log')

设置logger的level, level有以下几个级别:

CRITICAL = 50

FATAL = CRITICAL

ERROR = 40

WARNING = 30

WARN = WARNING

INFO = 20

DEBUG = 10

NOTSET = 0

如果把logger的level设置为INFO,那么小于INFO级别的日志都不输出, 大于等于INFO级别的日志都输出

 Formatter 格式化输出:

%(name)s Logger的名字 

%(levelno)s 数字形式的日志级别

%(levelname)s 文本形式的日志级别

%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有

%(filename)s 调用日志输出函数的模块的文件名

%(module)s 调用日志输出函数的模块名

%(funcName)s 调用日志输出函数的函数名

%(lineno)d 调用日志输出函数的语句所在的代码行

%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示

%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数

%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒

%(thread)d 线程ID。可能没有

%(threadName)s 线程名。可能没有

%(process)d 进程ID。可能没有

%(message)s用户输出的消息

对于上述记录日志的功能,只能将日志记录在单文件中,如果想要设置多个日志文件,logging.basicConfig将无法完成,需要自定义文件和日志操作对象。

# 定义文件

file_1_1 = logging.FileHandler('l1_1.log', 'a')

fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")

file_1_1.setFormatter(fmt)

file_1_2 = logging.FileHandler('l1_2.log', 'a')

fmt = logging.Formatter()

file_1_2.setFormatter(fmt)

# 定义日志

logger1 = logging.Logger('s1', level=logging.ERROR)

logger1.addHandler(file_1_1)

logger1.addHandler(file_1_2)

# 写日志

logger1.critical('1111')

日志(一)

View Code

# 定义文件

file_2_1 = logging.FileHandler('l2_1.log', 'a')

fmt = logging.Formatter()

file_2_1.setFormatter(fmt)

# 定义日志

logger2 = logging.Logger('s2', level=logging.INFO)

logger2.addHandler(file_2_1)

日志(二)

View Code

如上述创建的两个日志对象

  • 当使用【logger1】写日志时,会将相应的内容写入 l1_1.log 和 l1_2.log 文件中
  • 当使用【logger2】写日志时,会将相应的内容写入 l2_1.log 文件中

9、configparser

 configparser用于处理特定格式的文件,其本质上是利用open来操作文件。

# 注释1

; 注释2

[section1] # 节点

k1 = v1 # 值 options

k2:v2 # 值

[section2] # 节点

k1 = v1 # 值

指定格式

格式

1、获取所有节点:

import configparser

config = configparser.ConfigParser()

config.read('xxxooo', encoding='utf-8')

ret = config.sections()

print(ret)

sections获取节点

2、获取指定节点下所有的键值对

import configparser

config = configparser.ConfigParser()

config.read('xxxooo', encoding='utf-8')

ret = config.items('section1')

print(ret)

items获取所有的键值对

3、获取指定节点下所有的建

import configparser

config = configparser.ConfigParser()

config.read('xxxooo', encoding='utf-8')

ret = config.options('section1')

print(ret

options获取所有的键

4、获取指定节点下指定key的值

import configparser

config = configparser.ConfigParser()

config.read('xxxooo', encoding='utf-8')

v = config.get('section1', 'k1')

# v = config.getint('section1', 'k1')

# v = config.getfloat('section1', 'k1')

# v = config.getboolean('section1', 'k1')

print(v)

View Code

5、检查、删除、添加节点

import configparser

r = configparser.ConfigParser()

r.read('conf',encoding='utf-8')

print(r.has_section('o1')) #检查节点是否存在

检查

mport configparser

r = configparser.ConfigParser()

r.read('conf',encoding='utf-8')

r.remove_section('hello')

r.write(open('conf','w'))

删除

import configparser

r = configparser.ConfigParser()

r.read('conf',encoding='utf-8')

r.add_section('hello3')

r.write(open('conf','w')) #w只写相应的节点不清空内容,a追加 会复制一份内容然后追加

添加

6、检查、删除、设置指定组内的键值对

import configparser

r = configparser.ConfigParser()

r.read('conf',encoding='utf-8')

r.has_option('hello','arge') #给定节点和节点下的key 返回是否存在

检查

import configparser

r = configparser.ConfigParser()

r.read('conf',encoding='utf-8')

r.remove_option('hello','arge') #给定节点和节点下的key 删除

r.write(open('conf','w'))

删除

import configparser

r = configparser.ConfigParser()

r.read('conf',encoding='utf-8')

r.set('hello','arge','19') #节点名,key,values 进行添加

r.write(open('conf','w'))

设置 

10、subprocess

subprocess包主要功能是执行外部的命令和程序。

call()

父进程等待子进程完成,执行命令,返回状态码

ret = subprocess.call(["ls", "-l"], shell=False)

ret = subprocess.call("ipconfig", shell=True)

check_call() 

父进程等待子进程完成,如果执行状态码是 0 ,则返回0,否则抛异常

subprocess.check_call(["ls", "-l"])

subprocess.check_call("exit 1", shell=True)

check_output()

父进程等待子进程完成,返回子进程向标准输出的输出结果,如果状态码是 0 ,则返回执行结果,否则抛异常

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

import subprocess

rc = subprocess.call(["ls","-l"])

我们将程序名(ls)和所带的参数(-l)一起放在一个表中传递给subprocess.call(),可以通过一个shell来解释一整个字符串:

import subprocess

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

out = subprocess.call("cd ..", shell=True)

我们使用了shell=True这个参数。这个时候,我们使用一整个字符串,而不是一个表来运行子进程。Python将先运行一个shell,再用这个shell来解释这整个字符串。

subprocess.Popen(...)

 参数:

args:shell命令,可以是字符串或者序列类型(如:list,元组)

bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲

stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄

preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用

close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。

所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

shell:同上

cwd:用于设置子进程的当前目录

env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。

universal_newlines:不同系统的换行符不同,True -> 同意使用 \n

startupinfo与createionflags只在windows下有效

将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

View Code

 实例:

import subprocess

ret1 = subprocess.Popen(["mkdir","t1"])

ret2 = subprocess.Popen("mkdir t2", shell=True)

View Code

终端输入的命令分为两种:

  • 输入即可得到输出,如:ifconfig
  • 输入进行某环境,依赖再输入,如:python

import subprocess

obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)# 先进入到目录 然后创建t3

View Code

import  subprocess

a = subprocess.Popen(["python"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,universal_newlines=True)

a.stdin.write("print('hello')\n")

a.stdin.write("print('hello1')")

a.stdin.close()

cmd_out = a.stdout.read()

a.stdout.close()

cmd_error=a.stderr.read()

a.stderr.close()

print(cmd_out)

print(cmd_error)

标准输入、输出

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

obj.stdin.write("print(1)\n")

obj.stdin.write("print(2)")

out_error_list = obj.communicate()

print(out_error_list)

View Code

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

out_error_list = obj.communicate('print("hello")') #单条命令

print(out_error_list)

View Code

11、shutil

shutil.copyfileobj(fsrc, fdst[, length])

将文件内容拷贝到另一个文件中

import shutil

shutil.copyfileobj(open('conf','r'),open('log.log','w'))

View Code

shutil.copyfile(src, dst)

拷贝文件

shutil.copyfile('f1.log', 'f2.log')

View Code

shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变

shutil.copymode('f1.log', 'f2.log')

View Code

shutil.copystat(src, dst)
拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log')

View Code

shutil.copy(src, dst)
拷贝文件和权限

import shutil

shutil.copy('f1.log', 'f2.log')

View Code

shutil.copy2(src, dst)
拷贝文件和状态信息

import shutil

shutil.copy2('f1.log', 'f2.log')

View Code

shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹

import shutil

shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

View Code

shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件

import shutil

shutil.rmtree('folder1')

View Code

shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。

import shutil

shutil.move('folder1', 'folder3')

View Code

shutil.make_archive(base_name, format,...)

创建压缩包并返回文件路径,例如:zip、tar

创建压缩包并返回文件路径,例如:zip、tar

    • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
      如:www                        =>保存至当前路径
      如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
    • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
    • root_dir: 要压缩的文件夹路径(默认当前目录)
    • owner: 用户,默认当前用户
    • group: 组,默认当前组
    • logger: 用于记录日志,通常是logging.Logger对象

#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录

import shutil

ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')

#将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录

import shutil

ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')

View Code

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

import zipfile

# 压缩

z = zipfile.ZipFile('laxi.zip', 'w')

z.write('a.log')

z.write('data.data')

z.close()

# 解压

z = zipfile.ZipFile('laxi.zip', 'r')

z.extractall()

z.close()

zipfile解压缩

zipfile

import tarfile

# 压缩

tar = tarfile.open('your.tar','w')

tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log')

tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log')

tar.close()

# 解压

tar = tarfile.open('your.tar','r')

tar.extractall() # 可设置解压地址

tar.close()

tarfile解压缩

tarfile

字符串格式化

1、百分号方式

%[(name)][flags][width].[precision]typecode

  • (name)      可选,用于选择指定的key
  • flags          可选,可供选择的值有:

    • +       右对齐;正数前加正好,负数前加负号;
    • -        左对齐;正数前无符号,负数前加负号;
    • 空格    右对齐;正数前加空格,负数前加负号;
    • 0        右对齐;正数前无符号,负数前加负号;用0填充空白处

  • width         可选,占有宽度
  • .precision   可选,小数点后保留的位数
  • typecode    必选

    • s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置
    • r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置
    • c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
    • o,将整数转换成 八  进制表示,并将其格式化到指定位置
    • x,将整数转换成十六进制表示,并将其格式化到指定位置
    • d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
    • e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
    • E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
    • f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
    • F,同上
    • g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
    • G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
    • %,当字符串中存在格式化标志时,需要用 %%表示一个百分号

注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式

这里列出的格式化符合都比较简单,唯一想要强调一下的就是"%s"和"%r"的差别。看个简单的代码:

string = "Hello\tWill\n"

print "%s" %string

print "%r" %string

####output####

Hello Will

'Hello\tWill\n'

Python2.6开始,新增了一种格式化字符串的函数str.format(),通过这个函数同样可以对字符串进行格式化处理。在format()函数中,使用“{}”符号来当作格式化操作符。

2、Format方式

[[fill]align][sign][#][0][width][,][.precision][type]

    • ll           【可选】空白处填充的字符
    • align        【可选】对齐方式(需配合width使用)
      • <,内容左对齐
      • >,内容右对齐(默认)
      • =,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号+填充物+数字
      • ^,内容居中

    • sign         【可选】有无符号数字

      • +,正号加正,负号加负;
      •  -,正号不变,负号加负;
      • 空格 ,正号空格,负号加负;

    • #            【可选】对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
    • ,            【可选】为数字添加分隔符,如:1,000,000
    • width       【可选】格式化位所占宽度
    • .precision 【可选】小数位保留精度
    • type         【可选】格式化类型

      • 传入” 字符串类型 “的参数

        • s,格式化字符串类型数据
        • 空白,未指定类型,则默认是None,同s

      • 传入“ 整数类型 ”的参数

        • b,将10进制整数自动转换成2进制表示然后格式化
        • c,将10进制整数自动转换为其对应的unicode字符
        • d,十进制整数
        • o,将10进制整数自动转换成8进制表示然后格式化;
        • x,将10进制整数自动转换成16进制表示然后格式化(小写x)
        • X,将10进制整数自动转换成16进制表示然后格式化(大写X)

      • 传入“ 浮点型或小数类型 ”的参数

        • e, 转换为科学计数法(小写e)表示,然后格式化;
        • E, 转换为科学计数法(大写E)表示,然后格式化;
        • f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
        • F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
        • g, 自动在e和f中切换
        • G, 自动在E和F中切换
        • %,显示百分比(默认显示小数点后6位)

下面直接通过一些简单的例子演示format()函数的基本使用:

# 位置参数

print("{0} is {1} years old".format("Wilber", 28))

print("{} is {} years old".format("Wilber", 28))

print("Hi, {0}! {0} is {1} years old".format("Wilber", 28))

# 关键字参数

print("{name} is {age} years old".format(name = "Wilber", age = 28))

# 下标参数

li = ["Wilber", 28]

print("{0[0]} is {0[1]} years old".format(li))

# 填充与对齐

# ^、<、>分别是居中、左对齐、右对齐,后面带宽度

# :号后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充

print('{:>8}'.format('3.14'))

print('{:<8}'.format('3.14'))

print('{:^8}'.format('3.14'))

print('{:0>8}'.format('3.14'))

print('{:a>8}'.format('3.14'))

# 浮点数精度

print('{:.4f}'.format(3.1415926))

print('{:0>10.4f}'.format(3.1415926))

# 进制

# b、d、o、x分别是二进制、十进制、八进制、十六进制

print('{:b}'.format(11))

print('{:d}'.format(11))

print('{:o}'.format(11))

print('{:x}'.format(11))

print('{:#x}'.format(11))

print('{:#X}'.format(11))

# 千位分隔符

print('{:,}'.format(15700000000))

计算器源码

import  re

def mutl_div(arg):

'''

:param arg: 去除括号后的表达式 eg:'-40/5'

:return: 返回计算的结果

'''

while True:

arg = re.sub('\-\-', '+', arg) #表达式里的符号替换

arg = re.sub('\-\+', '-', arg)

arg = re.sub('\+\-', '-', arg)

arg = re.sub('\+\+', '+', arg)

str_split = re.split(r'(\d+\.?\d*[*/]-?\d+\.?\d*)', arg,1) #匹配公式里的乘除-->从左至右

if len(str_split) ==3:

a,b,c = str_split[0],str_split[1],str_split[2]

if '*' in b:

d,e = b.split('*')

ret = float(d) * float(e)

arg = a + str(ret) + c

else:

d, e = b.split('/')

ret = float(d) / float(e)

arg = a + str(ret) + c

else:

str_ret = re.findall(r'-?\d+\.?\d*',arg) #加减运算 思想获取表达式里所有的'-' 然后进行相加

w = 0

for x in str_ret:

w+=float(x)

return w

a = input('公式:')

while True:

b =a.replace(' ','')

ret = re.split('\(([^()]+)\)', b, 1)

if len(ret) == 3:

a,b,c = re.split('\(([^()]+)\)', b, 1)

rec = mutl_div(b)

a = a + str(rec) + c

else:

red = mutl_div(a)

print('计算结果:%s'%(red))

print('eval结果:%s'%(float(eval(b))))

break

  

 

 

 

  

以上是 Python系列之模块、和字符串格式化 的全部内容, 来源链接: utcz.com/z/387151.html

回到顶部