Title

subprocess模块,re模块,logging模块,XML模块,typing模块,包的简介

11.subprocess模块

subprocess模块可以通过python代码给操作系统终端发送命令,并且可以返回结果。该模块主要通过popen这个方法创建子进程,并连接它们的输入、输出和错误管道,执行cmd并获取它们的返回状态。

import subprocess
while True:
    # 让用户输入终端命令
    cmd_str = input('请输入终端命令:').strip()
   # 调用Popen就会将用户的终端命令发送给本地操作系统的终端
   # 得到一个对象,对象中包含着正确或错误的结果。
    obj = subprocess.Popen(
        cmd_str,shell=False,    # 默认是False,需要改成True
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    success = obj.stdout.read().decode('gbk')   # windows默认gbk格式
    if success: # 如果终端命令正确,输入成功
        print(success,'正确的结果')

    error = obj.stderr.read().decode('gbk')
    if error:  # 如果终端命令错误,输入失败
        print(error,'错误的结果')      

subprocess的run命令和popen命令类似。run会产生一个CompletedProcess的实例,以及returncode=0(0表示正常结束子进程),还有输出结果stdout,
popen 命令会产生一个subprocess.Popen object,通过read方法和decode方法可以取出输出结果,都有一个参数shell来控制是否用shell解释器来执行命令
poll()方法是检查进程是否结束,正常应该返回0

12.re模块和正则表达式

  • 什么是re模块和正则表达式

    正则表达式:

    正则表达式是一门独立的技术, 任何语言都可以使用正则表达式,正则表达式是由一堆特殊的字符组合而来的。

    字符组元字符 来 组合使用

    re模块:

    在python中,若想使用正则表达式,必须通过re模块来实现。

    字符组:  
        - [0-9] 可以匹配到一个0-9的字符  
        - [9-0]: 报错, 必须从小到大  
        - [a-z]: 从小写的a-z  
        - [A-Z]: 从大写A-Z  
        - [z-A]: 错误, 只能从小到大,根据ascii表来匹配大小。 
        - [A-z]: 总大写的A到小写的z。  
        注意: 顺序必须要按照ASCII码数值的顺序编写。
    

    元字符:https://images2015.cnblogs.com/blog/1036857/201705/1036857-20170529203214461-666088398.png

元字符组合使用

\w\W: 匹配字母数字下划线与非字母数字下划线,匹配所有。

\d\D: 无论是数字或者非数字都可以匹配。

^$: 配合使用叫做精准匹配,如何限制一个字符串的长度或者内容。

|: 或。ab|abc如果第一个条件成立,则abc不会执行,怎么解决,针对这种情况把长的写在前面就好了,一定要将长的放在前面。

re模块三种比较重要的方法:

# findall():
# 可以匹配 "所有字符" ,拿到返回的结果,返回的结果是一个列表。
import re
demo = 'Sean json tank' #(不要带逗号,否则会返回空列表
# res = re.findall(元字符,分割范围,需要分割的字符串)
res = re.findall('[A-z]{4}',demo)
print(res)   # 返回的结果是个列表
# 输出结果:['Sean', 'json', 'tank']



# #search():----> obj ----> obj.group()
# #在匹配一个字符成功后,拿到结果后结束,不往后匹配。
import re
demo1 = 'Sean json tank'
res1 = re.search('[A-z]{4}',demo1)
print(res1)    # 直接打印是一个re.Match object,需要group一下
print(type(res1))
print(res1.group())  # 找出第一个元素后就不会再往下找了
# 输出结果:Sean


# match():----> obj ----> obj.group()
import re
demo3 = 'Sean json tank'
res2 = re.match('[A-z]',demo3)
# print(res2)   # 从匹配字符的开头匹配,若开头不是想要的内容,则返回None,若是则继续往下匹配,直到全部匹配出结果
# print(res2.group())
if res2:     # 可以通过判断是否匹配成功
   print(res2)
   print('匹配成功')
else:
   print('匹配失败')

  • 为什么要使用正则

比如要获取“一堆字符串”中的“某些字符”,正则表达式可以帮我们过滤,并提取出想要的字符数据。

例如:'dkljdwqoweiurorwytfc nnclaxxnjspwacmjdssu;slaksdoa'

我们需要在上面的字符串里面提取dssu,则可以使用正则表达式取过滤提取我们需要的数据

应用场景:

  • 爬虫: re, BeautifulSoup4, Xpath, selector
  • 数据分析过滤数据: re, pandas, numpy...
  • 用户名与密码、手机认证:检测输入内容的合法性
    • 用户名: alex
  • 如何使用正则表达式和re模块
# 检测手机号码的合法性
import re
# phon_number = input('请输入11位手机号:').strip()
while True:
    phon_number = input('请输入11位手机号:').strip()
    # 需求: 11位、开头13/14/15/17/19
    #     # 参数1: 正则表达式  ''
    #     # 参数2: 需要过滤的字符串
    #     # ^: 代表“开头”
    #     # $: 代表“结束”
    #     # |: 代表“或”
    #     # (13|14): 可以获取一个值,判断是否是13或14.
    #     # {1}: 需要获取1个值 限制数量
    #     # []: 分组限制取值范围
    # #     # [0-9]: 限制只能获取0——9的某一个字符。
    # if re.match(参数1,参数2): match表示从头开始比较
    # if re.match('^(13|15|14|17|19)[0-9]{9}$',phon_number):
    if re.match('(13|15|14|17|19)[0-9]{9}', phon_number):
        print('手机号合法')
    #
    else:
        print('不合法')

13.logging模块

配置日志的模块

logging的配置信息
"""
logging配置
"""
import os

import logging.config

# 定义三种日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'

# 定义日志输出格式 结束
# ****************注意1: log文件的目录
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
logfile_dir = os.path.join(BASE_PATH, 'log')
# print(logfile_dir)

# ****************注意2: log文件名
logfile_name = 'user.log'

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)

# ****************注意3: log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
    },
    'filters': {},
    'handlers': {
        #打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,  # 日志文件
            'maxBytes': 1024*1024*5,  # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        #logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        },
    },
}


# 注意4:
def get_logger(user_type):
    # 1.加载log配置字典到logging模块的配置中
    logging.config.dictConfig(LOGGING_DIC)

    # 2.获取日志对象
    # logger = logging.getLogger('user')
    # logger = logging.getLogger('bank')
    # logger = logging.getLogger('shop')
    logger = logging.getLogger(user_type)
    return logger

# logging.config.dictConfig(LOGGING_DIC)
# # 调用获取日志函数的到日志对象
# logger = logging.getLogger('user')

# 通过logger日志对象,调用内部的日志打印
logger = get_logger('user')
# '只要思想不滑坡,方法总比问题多!'就是需要记录的日志信息
logger.info('学习不要浮躁,一步一个脚印!')
# logger.info('只要思想不滑坡,方法总比问题多!')

15.XML模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。

xml的格式如下,就是通过<>节点来区别数据结构的:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:

# print(root.iter('year')) #全文搜索
# print(root.find('country')) #在root的子节点找,只找一个
# print(root.findall('country')) #在root的子节点找,找所有
import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
 
#遍历xml文档
for child in root:
    print('========>',child.tag,child.attrib,child.attrib['name'])
    for i in child:
        print(i.tag,i.attrib,i.text)
 
#只遍历year 节点
for node in root.iter('year'):
    print(node.tag,node.text)
#---------------------------------------

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
    new_year=int(node.text)+1
    node.text=str(new_year)
    node.set('updated','yes')
    node.set('version','1.0')
tree.write('test.xml')
 
 
#删除node
for country in root.findall('country'):
   rank = int(country.find('rank').text)
   if rank > 50:
     root.remove(country)
 
tree.write('output.xml')
#在country内添加(append)节点year2
import xml.etree.ElementTree as ET
tree = ET.parse("a.xml")
root=tree.getroot()
for country in root.findall('country'):
    for year in country.findall('year'):
        if int(year.text) > 2000:
            year2=ET.Element('year2')
            year2.text='新年'
            year2.attrib={'update':'yes'}
            country.append(year2) #往country节点下添加子节点

tree.write('a.xml.swap')

自己创建xml文档:

import xml.etree.ElementTree as ET
 
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True)
 
ET.dump(new_xml) #打印生成的格式

16.typing模块

https://www.cnblogs.com/liuqingzheng/p/11012099.html#_label1

14.包

1.什么是包?

包是一个带有__ init__.py的文件夹,包也可以被导入,并且可以一并导入包下的所有模块。

2.为什么要使用包?

包可以帮我们管理模块,在包中有一个__init__.py, 由它来帮我们管理模块。

3.怎么使用包?

  • import 包.模块名
  • from 包 import 模块名
  • from 包.模块名 import 模块中的名字

4.导入包时发生的事情:

1.当包被导入时,会以包中的__ init __.py来产生一个名称空间。

2.然后执行__ init _.py文件, 会将 __ init __.py中的所有名字添加到名称空间中。

3.接着会将包下所有的模块的名字加载到__ init__.py产生的名称空间中。

4.导入的模块指向的名称空间其实就是_ini__.py产生的名称空间中。

posted @ 2019-11-19 22:57  Mr江  阅读(213)  评论(0编辑  收藏  举报