python高级(5)

一、正则表达式
• 在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个模块,名字为re,使用方法如下:
导入re模块

import re

使用match方法进行匹配操作

result = re.match(正则表达式,要匹配的字符串)

如果上一步匹配到数据的话,可以使用group方法来提取数据

result.group()

01、匹配单个字符

		.	匹配任意1个字符(除了\n)
		[ ]	匹配[ ]中列举的字符
		\d	匹配数字,即0-9
		\D	匹配非数字,即不是数字
		\s	匹配空白,即 空格,tab键
		\S	匹配非空白
		\w	匹配单词字符,即a-z、A-Z、0-9、_
		\W	匹配非单词字符

02、匹配多个字符

		*	匹配前一个字符出现0次或者无限次,即可有可无
		+	匹配前一个字符出现1次或者无限次,即至少有1次
		?	匹配前一个字符出现1次或者0次,即要么有1次,要么没有
		{m}	匹配前一个字符出现m次
		{m,n}	匹配前一个字符出现从m到n次

03、匹配开头结尾

		^	匹配字符串开头
		$	匹配字符串结尾

04、匹配分组

		|	匹配左右任意一个表达式
		(ab)	将括号中字符作为一个分组
		\num	引用分组num匹配到的字符串
		(?P<name>)	分组起别名
		(?P=name)	引用别名为name分组匹配到的字符串

二、线程
1.python中如何创建线程
○ 使用threading这个高级模块
○ 启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行
○ 如果需要主线程等待其他的子线程执行结束之后再终止,需要子线程调用join()函数。
○ 多线程程序的执行顺序是不确定的
2.多线程之间共享全局变量有2种方式:
□ 子线程函数使用global关键字来调用函数外全局变量
□ 列表当做实参传递到线程中
□ 在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
□ 缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)

      #创建线程
import threading
import time

def work():
    for i in range(10):
        print("正在工作中..")
        time.sleep(0.5)
if __name__ == '__main__':
    work_thread = threading.Thread(target=work)
    work_thread.start()

3.互斥锁
□ 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
□ 线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。
□ 互斥锁为资源引入一个状态:锁定/非锁定
□ 某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
□ threading模块中定义了Lock类,可以方便的处理锁定:

◊ # 创建锁
◊ mutex = threading.Lock()
◊ # 锁定
◊ mutex.acquire()
◊ # 释放
◊ mutex.release()

□ 注意:
◊ 如果这个锁之前是没有上锁的,那么acquire不会堵塞
◊ 如果在调用acquire对这个锁上锁之前 它已经被 其他线程上了锁,那么此时acquire会堵塞,直到这个锁被解锁为止
4.锁的优缺点
□ 锁的优点:
◊ 确保了某段关键代码只能由一个线程从头到尾完整地执行
□ 锁的缺点:
◊ 阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
◊ 由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁

import threading
#创建锁
lock = threading.Lock()
num = 0
def work1(n):
    # 加锁
    lock.acquire()
    for i in range(n):
        global num
        num+=1
    print("work1:",num)
    #释放锁
    lock.release()

def work2(n):
    # 加锁
    lock.acquire()
    for i in range(n):
        global num
        num+=1
    print("work2:",num)
    #释放锁
    lock.release()

if __name__ == '__main__':
    #创建线程
    work1_thread = threading.Thread(target=work1,args=(10000000,))
    work2_thread = threading.Thread(target=work2,args=(10000000,))
    #启动
    work1_thread.start()
    work2_thread.start()

5.死锁
□ 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
□ 尽管死锁很少发生,但一旦发生就会造成应用的停止响应。
□ 避免死锁
◊ 程序设计时要尽量避免(银行家算法)
◊ 添加超时时间等

import threading
import time

#创建锁
lock = threading.Lock()

#全局变量
alist = [1,2,3,4,5]
def work1():
    for i in range(10):
        # 加锁
        lock.acquire()
        if i < len(alist):
            print(alist[i])
            # 释放锁
            lock.release()
        else:
            print("列表空了")
            # 释放锁
            lock.release()
if __name__ == '__main__':
    work1_thread = threading.Thread(target=work1)
    work1_thread.start()

三、进程

1.进程是操作系统分配资源的基本单元。
2.进程、线程对比:
□ 进程在执行过程中拥有独立的内存单元,而多个线程共享进(进程所分配的资源)内存,从而极大地提高了程序的运行效率
3.创建进程-multiprocessing模块
○ 创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
4.进程间不共享全局变量

import multiprocessing
import time
import os
#工作任务
def work():
    ps = multiprocessing.current_process()
    print("子进程的编号:",ps.pid,os.getpid())
    print("子进程的父进程的编号:",os.getppid())
    print("work:",ps)
    for i in range(10):
        print("工作中。。。")
        time.sleep(0.1)
        #扩展:根据进程编号杀死指定进程
        os.kill(os.getpid(),9)
if __name__ == '__main__':
    ps = multiprocessing.current_process()
    print("main:",ps)
    print("主进程的编号:",ps.pid)
    #创建子进程
    #提示:group不需要设置,目前智能设置为None

5.进程间通信
• Process之间有时需要通信,可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个消息队列程序
• 初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头);
• Queue.qsize():返回当前队列包含的消息数量;
• Queue.empty():如果队列为空,返回True,反之False ;
• Queue.full():如果队列满了,返回True,反之False;
• Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True;


import multiprocessing
import time
def write_data(queue):
    for i in range(10):
        #如果队列长度为5,满了
        if queue.qsize() == 5:
            print("队列满了")
            break
        else:
            queue.put(i)
            print("写入数据:",i)
            time.sleep(0.2)
def read_data(queue):
    while True:
        if queue.qsize() == 0:
            print("队列空了")
            break
        else:
            ret = queue.get()
            print("取出数据:",ret)
            time.sleep(0.2)
if __name__ == '__main__':
    #创建队列
    queue = multiprocessing.Queue(5)
    #创建进程
    write_process = multiprocessing.Process(target=write_data,args=(queue,))
    read_process = multiprocessing.Process(target=read_data,args=(queue,))
    #启动进程
    write_process.start()
    write_process.join()
    read_process.start()

6.进程池
• 进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数
7.multiprocessing.Pool常用函数解析

• apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
• close():关闭Pool,使其不再接受新的任务;
• terminate():不管任务是否完成,立即终止;
• join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;

# 进程池
import multiprocessing
import time
import os
#复制文件
def copy_work():
    print(os.getpid())
    print("正在复制中。。。。")
    time.sleep(2)
if __name__ == '__main__':
    #创建一个进程池对象
    pool = multiprocessing.Pool(2)
    #批量创建进程
    for i in range(16):
        #以异步非阻塞
        pool.apply_async(copy_work)
    #关闭进程池防止新的进程流入
    pool.close()
    #启动进程池
    pool.join()

四、协程
○ python可以通过 yield/send 的方式实现协程,也可以使用第三方库中的greenlet来实现协程。
○ 协程的优势:
§ 协程的特点在于是一个线程执行
§ 所以协程最大的优势就是极高的执行效率。
§ 第二大优势就是不需要多线程的锁机制
执行效率比多线程高很多
○ 协程的缺陷
§ 1.无法利用多核资源:协程的本质是个单线程
§ 2.进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序。

#   协程
import time
#定义协程1
def work1():
    while True:
        print("work1..")
        time.sleep(0.5)
        yield
#定义协程2
def work2():
    while True:
        print("work2..")
        time.sleep(0.5)
        yield

if __name__ == '__main__':
    g1 = work1()
    g2 = work2()
    while True:
        next(g1)
        next(g2)

五、同步IO/异步IO
○ 同步IO操作:导致请求进程阻塞,直到IO操作完成。
○ 异步IO操作:不导致进程阻塞。
○ python实现异步IO的库:

□ gevent
□ asyncio

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值