Python学习笔记

为了打星水杯配合队友摸鱼突击学了一下,主要就是多线程多进程以及装饰器方面的知识,一知半解很粗浅

多线程

我的理解就是新开一个线程执行我给他分配的函数
_ t h r e a d . s t a r t _ n e w _ t h r e a d ( f u n c t i o n n a m e , a r g s ) \_thread.start\_new\_thread(function_{name}, args)\\ _thread.start_new_thread(functionname,args)
其中args以元组形式给出
先学了一下_thread

import _thread
import time


def print_time(outthing, delay):
    count = 2
    while count > 0:
        time.sleep(delay)
        count -= 1
        print("{}: now time is: {}".format(outthing, time.ctime(time.time()) ))


try:
    _thread.start_new_thread(print_time, ("Thread1", 1, ) )
    _thread.start_new_thread(print_time, ("Thread2", 3, ) )
except KeyboardInterrupt:
    print("你管他干嘛")

while True:
    pass

运行结果

Thread1: now time is: Fri Nov 19 11:10:37 2021
Thread1: now time is: Fri Nov 19 11:10:38 2021
Thread2: now time is: Fri Nov 19 11:10:39 2021
Thread2: now time is: Fri Nov 19 11:10:42 2021

但是网上都说这东西被淘汰了,所以我们用 t h r e a d i n g threading threading
使用Threading模块创建线程,直接从 t h r e a d i n g . T h r e a d threading.Thread threading.Thread继承,然后重写__ i n i t init init__方法和 r u n run run方法即可:

import time
import threading


class MyThread(threading.Thread):
    def __init__(self, ThreadID, delay, counter):
        threading.Thread.__init__(self)
        self.ThreadID = ThreadID
        self.delay = delay
        self.counter = counter

    def run(self):
        print("线程{}开始运行".format(self.ThreadID))
        print_time(self.ThreadID, self.delay, self.counter)
        print("线程{}结束运行".format(self.ThreadID))


def print_time(ThreadID, delay, t):
    count = t
    while count > 0:
        if Wrong_exit == 1:
            print("Error")
        time.sleep(delay)
        print("线程{}正在运行,现在的时间是:{}".format(ThreadID, time.ctime(time.time())))
        count -= 1


Wrong_exit = 0
f1 = MyThread("thread1", 1, 5)
f2 = MyThread("thread2", 2, 3)
f3 = MyThread("thread3", 4, 2)
f1.start()
f2.start()
f3.start()
f1.join()
f2.join()  # 这里的三个join保证了一定是三个子线程都结束了之后主线程才结束
f3.join()  # 不然可能会出现先输出所有线程执行完毕然后再输出线程thread结束运行
print("所有线程执行完毕")

运行结果
可以看到线程123是同时进行的

线程thread1开始运行
线程thread2开始运行
线程thread3开始运行
线程thread1正在运行,现在的时间是:Fri Nov 19 11:41:02 2021
线程thread2正在运行,现在的时间是:Fri Nov 19 11:41:03 2021
线程thread1正在运行,现在的时间是:Fri Nov 19 11:41:03 2021
线程thread1正在运行,现在的时间是:Fri Nov 19 11:41:04 2021
线程thread3正在运行,现在的时间是:Fri Nov 19 11:41:05 2021
线程thread2正在运行,现在的时间是:Fri Nov 19 11:41:05 2021
线程thread1正在运行,现在的时间是:Fri Nov 19 11:41:05 2021
线程thread1正在运行,现在的时间是:Fri Nov 19 11:41:06 2021
线程thread1结束运行
线程thread2正在运行,现在的时间是:Fri Nov 19 11:41:07 2021
线程thread2结束运行
线程thread3正在运行,现在的时间是:Fri Nov 19 11:41:09 2021
线程thread3结束运行
所有线程执行完毕

t h r e a d thread thread还提供了以下方法

r u n ( ) run() run(): 用以表示线程活动的方法。

s t a r t ( ) start() start():启动线程活动。

j o i n ( [ t i m e ] ) join([time]) join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出
未处理的异常-或者是可选的超时发生。
例如 . j o i n ( 5 ) .join(5) .join(5),等待最多 5 s 5s 5s或到调用结束

i s A l i v e ( ) isAlive() isAlive(): 返回线程是否活动的。

g e t N a m e ( ) getName() getName(): 返回线程名。

s e t N a m e ( ) setName() setName(): 设置线程名。

j o i n ( ) join() join()可以看上面的例子

t h r e a d i n g threading threading支持 L o c k Lock Lock来实现线程同步,也支持 Q u e u e Queue Queue方便多线程一起访问,这里只提供了 L o c k Lock Lock来实现同步的例子, Q u e u e Queue Queue就放在进程那了

import threading
import time


class MyThread(threading.Thread):
    def __init__(self, t_name, delay, q, counter):  # 记录线程名称,延迟时间,所使用的锁,播报次数
        threading.Thread.__init__(self)
        self.delay = delay
        self.name = t_name
        self.q = q
        self.counter = counter

    def run(self):
        print("{} begin running".format(self.name))
        print_time(self.name, self.delay, self.q, self.counter)


def print_time(name, delay, q, counter):
    q.acquire()  # 锁上
    while counter > 0:
        time.sleep(delay)
        print("{} tells you, now time is: {} ".format(name, time.ctime()))
        counter -= 1
    print("")
    q.release()  # 在最后这个线程结束时开锁


if __name__ == "__main__":
    queueLock = threading.Lock()
    q1 = MyThread("q1", 1, queueLock, 3)
    q2 = MyThread("q2", 2, queueLock, 2)
    q1.start()
    q2.start()

运行结果很明显
q1和q2虽然同时启动,但是q1结束才开始运行q2

q1 begin running
q2 begin running
q1 tells you, now time is: Fri Nov 19 11:25:28 2021 
q1 tells you, now time is: Fri Nov 19 11:25:29 2021 
q1 tells you, now time is: Fri Nov 19 11:25:30 2021 

q2 tells you, now time is: Fri Nov 19 11:25:32 2021 
q2 tells you, now time is: Fri Nov 19 11:25:34 2021 

多进程

我的理解就是新开一个进程执行我给他分配的函数怎么和线程差不多
我们使用 m u l t i p r o c e s s i n g multiprocessing multiprocessing
p = m u l t i p r o c e s s i n g . P r o c e s s ( t a r g e t = f u n c , a r g s = 元 组 ) p = multiprocessing.Process(target = func, args = 元组) p=multiprocessing.Process(target=func,args=)
f u n c func func就是函数名称, a r g s args args则是以元组形式提供的参数组

import multiprocessing
import time


def print_time(delay, counter, Proname):
    while counter > 0:
        print("{} tells you, now time is: {}".format(Proname, time.ctime()))
        time.sleep(delay)
        counter -= 1


if __name__ == '__main__': # 这句一定要加
    f1 = multiprocessing.Process(target=print_time, args=(2, 2, "Pro1"))
    f2 = multiprocessing.Process(target=print_time, args=(1, 3, "Pro2"))
    f1.start()
    f2.start()

结果

Pro2 tell s you,now time is :Fri Nov 19 11:46:20 2021
Pro1 tell s you,now time is :Fri Nov 19 11:46:20 2021
Pro2 tell s you,now time is :Fri Nov 19 11:46:21 2021
Pro1 tell s you,now time is :Fri Nov 19 11:46:22 2021
Pro2 tell s you,now time is :Fri Nov 19 11:46:22 2021

我们把进程定义为类,从 m u l t i p r o c e s s i n g . P r o c e s s multiprocessing.Process multiprocessing.Process来继承
这一块和线程都差不多

import multiprocessing
import time


class MyProcess(multiprocessing.Process):
    def __init__(self, Proname, delay, counter):
        multiprocessing.Process.__init__(self)
        self.name = Proname
        self.delay = delay
        self.counter = counter

    def run(self):
        print("{} start running".format(self.name))
        print_time(self.name, self.delay, self.counter)
        print("{} end running".format(self.name))


def print_time(Proname, delay, counter):
    while counter > 0:
        counter -= 1
        time.sleep(delay)
        print("{} tells you now time is {}".format(Proname, time.ctime()))


if __name__ == "__main__":
    MyPro1 = MyProcess("p1", 1, 3)
    MyPr02 = MyProcess("p2", 2, 2)
    MyPro1.start()
    MyPr02.start()

结果

p1 start running
p2 start running
p1 tells you now time is Fri Nov 19 11:47:57 2021
p2 tells you now time is Fri Nov 19 11:47:58 2021
p1 tells you now time is Fri Nov 19 11:47:58 2021
p1 tells you now time is Fri Nov 19 11:47:59 2021
p1 end running
p2 tells you now time is Fri Nov 19 11:48:00 2021
p2 end running

方法:
i s _ a l i v e ( ) 、 j o i n ( [ t i m e o u t ] ) 、 r u n ( ) 、 s t a r t ( ) 、 t e r m i n a t e ( ) is\_alive()、join([timeout])、run()、start()、terminate() is_alive()join([timeout])run()start()terminate()。其中, P r o c e s s Process Process s t a r t ( ) start() start()启动某个进程。

属性 我就用过一个 d a e m o n daemon daemon
d a e m o n daemon daemon是父进程终止后自动终止,且自己不能产生新进程,必须在父进程 s t a r t ( ) start() start()之前设置。例如:

 p = multiprocessing.Process(target = worker, args = (3,))
 p.daemon = True

一些组件

Lock()

当多个进程需要访问共享资源的时候, L o c k Lock Lock可以用来避免访问的冲突。
就是锁上只让一个运行
有两种写法,一种是用 w i t h with with,一种就是标准的 . a c q u i r e ( ) .acquire() .acquire()

import multiprocessing


class MyProcess(multiprocessing.Process):
    def __init__(self, Proname, f, times, lock):
        multiprocessing.Process.__init__(self)
        self.f = f
        self.lock = lock
        self.name = Proname
        self.times = times

    '''def run(self):
        fs = open(self.f, 'a+')
        fs.write("{} is running\n".format(self.name))
        fs.close()
        with self.lock:              # 在这锁上 
            while self.times > 0:
                getF(self.name, self.times, open(self.f, 'a+'))
                self.times -= 1      # 在这解锁
        fs = open(self.f, 'a+')
        fs.write("{} is ending\n".format(self.name))
        fs.write("\n")
        fs.close()'''
        
    def run(self):
        fs = open(self.f, 'a+')
        fs.write("{} is starting\n".format(self.name))
        fs.close()
        self.lock.acquire()         # 锁上
        while self.times > 0:
            self.times -= 1
            getF(self.name, self.times, open(self.f, 'a+'))
        fs = open(self.f, 'a+')
        fs.write("{} is ending\n".format(self.name))
        fs.write("\n")
        self.lock.release()         # 解锁
        fs.close()


def getF(name, times, f):
    f.write(name + "\n")
    f.close()


if __name__ == "__main__":
    lock = multiprocessing.Lock()
    p1 = MyProcess("p1", "readme.txt", 5, lock)
    p2 = MyProcess("p2", "readme.txt", 3, lock)
    p1.start()
    p2.start()
    print("end")

输出结果(来自文件)

p1 is starting
p2 is starting
p1
p1
p1 is ending

p2
p2 is ending
Semaphore和Event

S e m a p h o r e Semaphore Semaphore
用来控制对共享资源的访问数量,例如池的最大连接数。
s = m u l t i p r o c e s s i n g . S e m a p h o r e ( 2 ) s = multiprocessing.Semaphore(2) s=multiprocessing.Semaphore(2) 只能同时运行两个进程(不包括主进程),其实就是剩余位置上限 2
s . a c q u i r e ( ) s.acquire() s.acquire()进程占用一个位置,剩余位置数量减一变成1
s . r e l e a s e ( ) s.release() s.release()进程让出自己的位置,剩余位置加一回到2
当剩余位置变成0后,再 a c q u i r e acquire acquire就必须等待前面有进程让位了

E v e n t Event Event
他可以让一群等某一个或多个进程都执行完之后再运行
e e = m u l t i p r o c e s s i n g . E v e n t ( ) ee = multiprocessing.Event() ee=multiprocessing.Event()

e . w a i t ( ∣ t i m e ∣ ) e.wait(|time|) e.wait(time)在时间 t i m e time time过去之前或 e . i s _ s e t ( ) e.is\_set() e.is_set()变成 T r u e True True之前都等待

e . s e t ( ) e.set() e.set()使 e . i s _ s e t ( ) e.is\_set() e.is_set()变成 T r u e True True

e . c l e a r ( ) e.clear() e.clear()使 e . i s _ s e t ( ) e.is\_set() e.is_set()变成 F a l s e False False

我用上面俩写了一个很有意思的汽车过马路( E v e n t Event Event控制)
有两个灯,只有都变绿了车才能通过,两个灯的红灯时间一次只能等一个
( S e m a p h o r e Semaphore Semaphore控制)

import multiprocessing
import time


class MyProcess(multiprocessing.Process):
    def __init__(self, process_name, e):
        multiprocessing.Process.__init__(self)
        self.process_name = process_name
        self.e = e

    def run(self):
        print("car {} come".format(self.process_name))
        car(self.e, self.process_name)


class Light(multiprocessing.Process):
    def __init__(self, last, s, name):
        multiprocessing.Process.__init__(self)
        self.last = last
        self.s = s
        self.name = name

    def run(self):
        light(self.s, self.name, self.last)


def light(s, name, last):
    s.acquire()
    time.sleep(last)
    print("light " + name + " is green\n")
    s.release()


def car(e, car_name):
    if not e.is_set():
        print("red, {} can't go\n".format(car_name))
    e.wait()  # 等绿灯
    print("green, {} go go go".format(car_name))


if __name__ == "__main__":
    ss = multiprocessing.Semaphore(1)  # 灯一次只能变一个
    ee = multiprocessing.Event()
    cars = []

    for i in range(1, 6):  # 六辆车
        f = MyProcess("p" + str(i), ee)
        cars.append(f)
        f.start()

    l1 = Light(2, ss, "l1")
    l2 = Light(3, ss, "l2")
    l2.start()
    l1.start()

    while True:
        num = 0
        if l1.is_alive():
            num += 1
        if l2.is_alive():
            num += 1  # 判断是不是都结束了
        if num == 0:
            ee.set()
            print("all lights are green\n")
            break
    try:
        while True:  # 隔一秒监测一下是不是所有车都过去了
            flag = 1
            for i in cars:
                if i.is_alive():
                    flag = 0
            if flag == 0:
                time.sleep(1)
                exit(0)
    except KeyboardInterrupt:
        print("手动阻止")
    except UnboundLocalError:
        print("变量未命名")
    finally:
        print("all car across")

结果

car p1 come
red, p1 can't go

car p2 come
red, p2 can't go

car p3 come
red, p3 can't go

car p4 come
red, p4 can't go

car p5 come
red, p5 can't go

light l1 is green

light l2 is green

all lights are green

green, p1 go go go
green, p2 go go go
green, p3 go go go
green, p5 go go go
green, p4 go go go
all car across
Queue

提供一个所有进程都能访问的队列
p u t put put方法
用以插入数据到队列中,put方法还有两个可选参数: b l o c k e d blocked blocked t i m e o u t timeout timeout
如果 b l o c k e d blocked blocked T r u e True True(默认值),并且 t i m e o u t timeout timeout为正值,该方法会阻塞 t i m e o u t timeout timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出 Q u e u e . F u l l Queue.Full Queue.Full异常。
如果 b l o c k e d blocked blocked F a l s e False False,但该 Q u e u e Queue Queue已满,会立即抛出 Q u e u e . F u l l Queue.Full Queue.Full异常。

g e t get get方法
从队列读取并且删除一个元素。同样, g e t get get方法有两个可选参数: b l o c k e d blocked blocked t i m e o u t timeout timeout
如果 b l o c k e d blocked blocked T r u e True True(默认值),并且 t i m e o u t timeout timeout为正值,那么在等待时间内没有取到任何元素,会抛出 Q u e u e . E m p t y Queue.Empty Queue.Empty异常。
如果 b l o c k e d blocked blocked F a l s e False False,有两种情况存在,如果 Q u e u e Queue Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出 Q u e u e . E m p t y Queue.Empty Queue.Empty异常。
使用了Event保证所有数都插入完了再取数

import multiprocessing
import time


class WriteProcess(multiprocessing.Process):
    def __init__(self, number, q):
        multiprocessing.Process.__init__(self)
        self.number = number
        self.q = q

    def run(self):
        print("wait for write")
        write_text(self.number, self.q)


class ReadProcess(multiprocessing.Process):
    def __init__(self, q, loc):
        multiprocessing.Process.__init__(self)
        self.q = q
        self.loc = loc

    def run(self):
        read_text(self.q, self.loc)


def write_text(get_in, q):
    try:
        q.put(get_in, block=False)
    except:
        pass
    finally:
        print("successfully get in")


def read_text(q, loc):
    try:
        loc.wait()
        print("wait for read")
        while q.qsize() > 0:
            print("successfully get out: ", q.get(block=False))
    except :
        print("blank queue")


if __name__ == "__main__":
    lo = multiprocessing.Event()
    a = int(input())
    b = int(input())
    qq = multiprocessing.Queue()
    q1 = WriteProcess(a, qq)
    q2 = WriteProcess(b, qq)
    q3 = ReadProcess(qq, lo)
    q1.start()
    q2.start()
    q3.start()
    while True:
        num = 0
        if q1.is_alive():
            num += 1
        if q2.is_alive():
            num += 1
        if num == 0:
            lo.set()
            break

结果

4
5
wait for write
wait for write
successfully get in
successfully get in
wait for read
successfully get out:  5
successfully get out:  4
Pipe

用不到好像就咕咕咕了

Pool

感觉和 S e m a p h o r e Semaphore Semaphore有点像,可以选择异步和并步
a p p l y 、 a s y n c apply、_async applyasync ( f u n c , a r g s ) (func, args) (func,args)它是非阻塞
他的返回值需要写 c a l l b a c k callback callback参数
p o o l 1 = m u l t i p r o c e s s i n g . P o o l ( p r o c e s s e s = 2 ) pool1 = multiprocessing.Pool(processes=2) pool1=multiprocessing.Pool(processes=2)
p o o l 1. a p p l y _ a s y n c ( p r i n t _ t i m e , ( 元 组 ) , c a l l b a c k = o u t ) pool1.apply\_async(print\_time, (元组), callback=out) pool1.apply_async(print_time,(),callback=out)
p r i n t _ t i m e print\_time print_time o u t out out都是函数, o u t out out的函数参数就是 p r i n t _ t i m e print\_time print_time的返回值

a p p l y apply apply ( f u n c , a r g s ) (func, args) (func,args)是阻塞的,返回值直接就是进程运行完的返回值

c l o s e ( ) close() close()关闭 p o o l pool pool,使其不在接受新的任务。

t e r m i n a t e ( ) terminate() terminate()结束工作进程,不在处理未完成的任务。

j o i n ( ) join() join()主进程阻塞,等待子进程的退出,
j o i n join join方法要在 c l o s e close close t e r m i n a t e terminate terminate之后使用。

import multiprocessing
import time


def print_time(name, delay, counter):
    while counter > 0:
        print("{} tells you, now time is {}".format(name, time.ctime()))
        time.sleep(delay)
        counter -= 1
    return "done" + name


def out(msg):
    print("now" + msg)


if __name__ == "__main__":
    result = []

    pool1 = multiprocessing.Pool(processes=2)
    for i in range(1, 5):
        pool1.apply_async(print_time, ("p" + str(i), i, 5 - i,), callback=out)
    pool1.close()
    pool1.join()

    pool = multiprocessing.Pool(processes=2)
    for i in range(1, 5):
        result.append(pool.apply(print_time, ("p" + str(i), i, 5 - i,)))
    pool.close()
    pool.join()
    for res in result:
        print("now" + res)

装饰器

分为含参不含参
类装饰器和函数装饰器

不含参函数装饰器

import time


def showtime(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print('spend is {}'.format(end_time - start_time))
    return wrapper


@showtime
def foo():
    print('foo..')


foo()

含参装饰器(装饰函数)

def outside(flag=0):
    def show_times(func):
        def count(a, b):
            start_time = time.time()
            func(a, b)
            end_time = time.time()
            print("spend is {}".format(end_time - start_time))

            if flag == 1:
                print("我是特殊的")
        return count
    return show_times


@outside(0)
def test(a, b):
    print(a+b)
    time.sleep(2)


a1 = int(input())
b1 = int(input())
test(a1, b1)

类装饰器
主要通过内部的__ c a l l call call__方法

import time


class Decor:
    def __init__(self, func):
        self.func = func

    def __call__(self, a, b):
        start_time = time.time()
        self.func(a, b)
        end_time = time.time()
        print("It costs {}".format(end_time - start_time))


@Decor
def test(a, b):
    print(a + b)
    time.sleep(2)


a1 = int(input())
b1 = int(input())
test(a1, b1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值