为了打星水杯配合队友摸鱼突击学了一下,主要就是多线程多进程以及装饰器方面的知识,一知半解很粗浅
多线程
我的理解就是新开一个线程执行我给他分配的函数
_
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
apply、async
(
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)