levels of contents

Python自动化学习笔记(十)——多进程,多线程,异常处理,faker模块,sys模块,jsonpath模块

1.多线程

1.1多线程创建和启动

  • 进程:一些资源的集合
  • 线程:程序执行的最小单位
  • 线程包含在进程内,进程是由若干线程组成的,一个进程至少有一个线程。
  • 多任务可以由多进程完成,也可以由一个进程内的多线程完成。

启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行,循环创建线程时,应当全部创建完毕后,再循环每一个线程执行t.join,否则和串行效率就一样了,代码示例:

import threading
import time
def run():
    time.sleep(1)
    print('run.............')
starttime=time.time()
threads=[]
for i in range(20):#循环创建20个线程
    t1=threading.Thread(target=run,) #实例化一个线程
    threads.append(t1)
    t1.start()#启动线程
# for t in threads:#循环每一个线程并t.join来等待
#     t.join()   #主线程等待子线程执行结束
while threading.active_count()!=1:
    pass
endtime=time.time()
print(endtime-starttime)

 

一个多线程下载图片的例子如下

两个知识点:

  • 多线程运行时拿不到函数的返回值,可以定义一个全局变量,把返回值存储到全局变量中
  • 实例化线程时,函数运行的参数可以通过一个list传入,t=threading.Thread(target=download_pic,args=(url,))
import requests
from hashlib import md5
import threading
import time
filename=[]
def download_pic(url):
    r=requests.get(url)
    file_name=md5(r.content).hexdigest()    #文件内容md5后的字符串拿来当作文件名
    with open(file_name+'.jpg','wb')as fw:
        fw.write(r.content)
    filename.append(file_name)    #多线程运行时拿不到函数的返回值,可以定义一个全局变量,把返回值存储到全局变量中

urls = [
     'https://cn.bing.com/az/hprichbg/rb/GoldenEagle_ZH-CN2823955379_1920x1080.jpg',
    'https://cn.bing.com/az/hprichbg/rb/GoldenEagle_ZH-CN2823955379_1920x1080.jpg',
    'https://cn.bing.com/az/hprichbg/rb/NapoleonsHat_ZH-CN2968205603_1920x1080.jpg',
    'https://cn.bing.com/az/hprichbg/rb/Snowkiters_ZH-CN3098762517_1920x1080.jpg'
]
start_time=time.time()
#单线程下载
# for url in urls:
#     download_pic(url)
#多线程下载
for url in urls:
    t=threading.Thread(target=download_pic,args=(url,))
    t.start()

while threading.active_count()!=1:
    pass
end_time=time.time()
print('下载完成,下载时间为%s'%(end_time-start_time))
print('下载图片文件名称分别为:',filename)

2.2 锁

确保一个线程在修改一个参数时,别的线程一定不能改,我们可以给这个参数加一把锁,修改完毕后再释放锁

import threading
count=0
lock=threading.Lock()   #申请一把锁,多个线程操作同一个数据时,要加锁
def run():
    global count
    with lock:  #加锁,python3会自动加锁
        count+=1
for i in range(10):
    t=threading.Thread(target=run,)
    t.start()

while threading.active_count()!=1:
    pass
print(count)

不写with lock的话,加锁和释放锁的方法分别是: lock.acquire()和lock.release()

2.3守护线程

#守护线程:守护主线程,主线程执行完成后子线程立即结束
import threading
import time
def run():
    time.sleep(5)
    print('run...')

for i in range(100):
    puren=threading.Thread(target=run)
    puren.setDaemon(True)#设置子线程为守护线程
    puren.start()

print('over')

输出如下,子线程的run方法还没有执行就结束了,因为主线程结束了,所以守护线程立即结束

 

2.多进程

在Python中,多个线程也只能利用一个cpu核心,如果想要实现多核任务,把每个cpu核心都利用起来,只能使用多进程来实现。通常我们可以利用多线程来执行IO密集型任务,多进程来执行CPU密集型任务

下面的例子演示了循环启动多个子进程并等待其结束:

import multiprocessing
import time

def run():
    time.sleep(2)
    print('run...')

if __name__ == '__main__':
    for i in range(10):
        p=multiprocessing.Process(target=run)   #实例化一个进程
        p.start()                               #启动一个进程

    while multiprocessing.active_children():#等待其他子进程运行完毕
        pass

多进程传入调用函数参数的方法和多线程的一致,p=multiprocessing.Process(target=run,args=(url,)) 

3.异常处理

3.1 try-except

语法示例如下:

d={}
l=[]
try:
    print(d['name'])
    print(l[-1])
except KeyError as e:   #多个异常,多个except
    print('字典里没有这个key',e)
except IndexError as e:
    print('出错了,下标越界',e)

except Exception as e:      #捕捉所有异常
    print('出现异常了',e)
else:                       #没有出现异常时
    print('没有异常')
finally:
    print('finally')

ps:finally里的语句一定会执行

3.2 自定义异常

class NumberError(Exception):    #定义一个异常类,继承Exception
    pass

class M:
    def Main(self):
        count=input('请输入要产生多少条银行卡号')
        if not count.isdigit():
            raise NumberError   #抛出一个异常
        for i in range(int(count)):
                self.card()

m=M()
m.Main()

输出为:

 4.sys.argv

通过sys模块下的argv属性,可以获取运行python文件的时候传入的参数,代码示例:

import sys
print(sys.argv)     #获取运行python文件的时候传入的参数
if len(sys.argv)>1:
    if sys.argv[1]=='--help':
        quit('这个python是用来测试的,运行的时候需要使用python a.py port')
    else:
        port=sys.argv[1]else:
    port=7878
import flask
server = flask.Flask(__name__)

@server.route('/')
def index():
    return '<h1>首页</h1>'

server.run(port=port)

以上代码,如果运行Python文件时输入:python sys模块.py 8888,则启动接口的端口为8888,如下图所示,不添加参数,默认启动,则端口为7878,传入多个参数时,用空格隔开

在pycharm运行代码时,在下图位置设置参数,再运行,也可以将参数传入

5.faker模块

faker模块是一个很强大的外部模块,可以生成各种数据,例如身份证号,电话号码,人名,地址等。示例:

from faker import Faker
f=Faker(locale='zh_CN')    #实例化
print(f.name()) #人名
print(f.postcode())#邮编
print(f.credit_card_number())   #身份证号
print(f.ssn())#身份证号
print(f.ipv4()) #ip地址
print(f.password()) #密码
print(f.address()) #地址
print(f.user_name()) #用户名

6.jsonpath

利用jsonpath模块可以快速找到json字典里的key,字典内有多重嵌套时非常好用,示例如下:

 

d={
        "error_code": 0,
        "stu_info": [
                {
                        "id": 2059,
                        "name": "小白",
                        "sex": "",
                        "age": 28,
                        "addr": "河南省济源市北海大道32号",
                        "grade": "天蝎座",
                        "phone": "18378309272",
                        "gold": 10896,
                        "info":{"card":23333,"bank_name":"中国银行"}
                },
                {
                        "id": 2067,
                        "name": "小名",
                        "sex": "",
                        "age": 28,
                        "addr": "河南省济源市北海大道32号",
                        "grade": "天蝎座",
                        "phone": "12345678915",
                        "gold": 100
                },
                {
                        "id": 2086,
                        "name": "小红",
                        "sex": "",
                        "age": 28,
                        "addr": "河南省济源市北海大道32号",
                        "grade": "狮子座",
                        "phone": "15837627044",
                        "gold": 4040
                },
                {
                        "id": 2095,
                        "name": "小懒",
                        "sex": "",
                        "age": 24,
                        "addr": "河南省项城市秣陵镇",
                        "grade": "摩羯座",
                        "phone": "13608417301",
                        "gold": 100
                },
                {
                        "id": 2107,
                        "name": "小黑",
                        "sex": "",
                        "age": 10,
                        "addr": "河南省康定大道158号",
                        "grade": "水瓶座",
                        "phone": "17612227885",
                        "gold": 700
                },
                {
                        "id": 2142,
                        "name": "小允",
                        "sex": "",
                        "age": 24,
                        "addr": "河南省项城市秣陵镇",
                        "grade": "摩羯座",
                        "phone": "13608417304",
                        "gold": 100
                },
                {
                        "id": 2240,
                        "name": "小黄",
                        "sex": "",
                        "age": 28,
                        "addr": "深圳市南山区",
                        "grade": "天蝎座",
                        "phone": "12456785512",
                        "gold": 100
                }
        ]
}
import jsonpath
res=jsonpath.jsonpath(d,'$.stu_info[0].info.bank_name')
print(res)
res=jsonpath.jsonpath(d,'$..bank_name')     #查找内部key,存在的话返回key的value,不存在返回false
print(res)
res=jsonpath.jsonpath(d,'$..error_code')     #查找内部key,存在的话返回key的value,不存在返回false
print(res)
res=jsonpath.jsonpath(d,'$..bakkk')             #查找内部key,存在的话返回key的value,不存在返回false
print(res)

 

输出结果为:

 

posted @ 2019-01-18 17:26  非文艺女青年  阅读(432)  评论(0编辑  收藏  举报
levels of contents