Python learning notes

Keywords: Python

In order to play the star water cup, I studied it with my teammates in fishing raids, mainly the knowledge of multithreading, multi process and decorators. I know a little about it

Multithreading

My understanding is to open a new thread to execute the functions I assigned to it
_ 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)
Where args is given in tuple form
I learned it first_ 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("What do you care about him")

while True:
    pass

Operation results

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

But the Internet says this thing has been eliminated, so we use it t h r e a d i n g threading threading
Use the Threading module to create threads directly from t h r e a d i n g . T h r e a d threading.Thread threading.Thread inherits and then overrides__ i n i t init init__ Methods and r u n run run method:

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("thread {}Start running".format(self.ThreadID))
        print_time(self.ThreadID, self.delay, self.counter)
        print("thread {}End operation".format(self.ThreadID))


def print_time(ThreadID, delay, t):
    count = t
    while count > 0:
        if Wrong_exit == 1:
            print("Error")
        time.sleep(delay)
        print("thread {}Is running. The current time is:{}".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()  # The three join s here ensure that the main thread will not end until all three sub threads have ended
f3.join()  # Otherwise, it may occur that all threads are output first, and then thread is output to end the operation
print("All threads finished executing")

Operation results
You can see that thread 123 is running at the same time

thread  thread1 Start running
 thread  thread2 Start running
 thread  thread3 Start running
 thread  thread1 Is running. The current time is: Fri Nov 19 11:41:02 2021
 thread  thread2 Is running. The current time is: Fri Nov 19 11:41:03 2021
 thread  thread1 Is running. The current time is: Fri Nov 19 11:41:03 2021
 thread  thread1 Is running. The current time is: Fri Nov 19 11:41:04 2021
 thread  thread3 Is running. The current time is: Fri Nov 19 11:41:05 2021
 thread  thread2 Is running. The current time is: Fri Nov 19 11:41:05 2021
 thread  thread1 Is running. The current time is: Fri Nov 19 11:41:05 2021
 thread  thread1 Is running. The current time is: Fri Nov 19 11:41:06 2021
 thread  thread1 End operation
 thread  thread2 Is running. The current time is: Fri Nov 19 11:41:07 2021
 thread  thread2 End operation
 thread  thread3 Is running. The current time is: Fri Nov 19 11:41:09 2021
 thread  thread3 End operation
 All threads finished executing

t h r e a d thread thread also provides the following methods

r u n ( ) run() run(): the method used to represent thread activity.

s t a r t ( ) start() start(): start thread activity.

j o i n ( [ t i m e ] ) join([time]) join([time]): wait until the thread aborts. This blocks the calling thread until the thread's join() method is called to abort - normal exit or throw
Unhandled exception - or an optional timeout occurred.
for example . j o i n ( 5 ) .join(5) . join(5), wait up to 5 s 5s 5s or to the end of the call

i s A l i v e ( ) isAlive() isAlive(): Returns whether the thread is active.

g e t N a m e ( ) getName() getName(): returns the thread name.

s e t N a m e ( ) setName() setName(): sets the thread name.

j o i n ( ) join() join() can be seen in the above example

t h r e a d i n g threading threading support L o c k Lock Lock to achieve thread synchronization, also support Q u e u e Queue Queue is convenient for multiple threads to access together. Only L o c k Lock Lock to achieve synchronization, Q u e u e Queue The Queue is placed in the process

import threading
import time


class MyThread(threading.Thread):
    def __init__(self, t_name, delay, q, counter):  # Record thread name, delay time, lock used, and number of broadcasts
        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()  # Lock
    while counter > 0:
        time.sleep(delay)
        print("{} tells you, now time is: {} ".format(name, time.ctime()))
        counter -= 1
    print("")
    q.release()  # Unlock at the end of the last thread


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

The operation results are obvious
q1 and q2 are started at the same time, but q2 starts only after q1 ends

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 

Multi process

My understanding is to open a new process to execute the functions I assigned to it. How is it similar to a thread
We use m u l t i p r o c e s s i n g multiprocessing multiprocessing class
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 = element group ) p = multiprocessing.Process(target = func, args = tuple) p=multiprocessing.Process(target=func,args = tuple)
f u n c func func is the name of the function, a r g s args args is the parameter group provided in tuple form

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__': # This sentence must be added
    f1 = multiprocessing.Process(target=print_time, args=(2, 2, "Pro1"))
    f2 = multiprocessing.Process(target=print_time, args=(1, 3, "Pro2"))
    f1.start()
    f2.start()

result

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

We define a process as a class from 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 to inherit
This piece is similar to threads

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()

result

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

method:
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(). Among them, P r o c e s s Process Process to s t a r t ( ) start() start() starts a process.

I used one d a e m o n daemon daemon
d a e m o n daemon The daemon is automatically terminated after the parent process terminates, and it cannot generate a new process itself. It must be in the parent process s t a r t ( ) start() Set before start(). For example:

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

Some components

Lock()

When multiple processes need to access shared resources, L o c k Lock Lock can be used to avoid access conflicts.
Just lock it and let only one run
There are two ways to write, one is to use w i t h with with, one is standard . 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:              # Lock it here 
            while self.times > 0:
                getF(self.name, self.times, open(self.f, 'a+'))
                self.times -= 1      # Unlock here
        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()         # Lock
        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()         # Unlock
        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")

Output results (from file)

p1 is starting
p2 is starting
p1
p1
p1 is ending

p2
p2 is ending

Semaphore and Event

S e m a p h o r e Semaphore Semaphore
Used to control the number of accesses to shared resources, such as the maximum number of connections to the pool.
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) can only run two processes at the same time (excluding the main process), which is actually the upper limit of the remaining position 2
s . a c q u i r e ( ) s.acquire() s. The acquire () process occupies one location, and the number of remaining locations is reduced by one to 1
s . r e l e a s e ( ) s.release() s. The release () process gives up its position, and the remaining positions are added by one back to 2
When the remaining position becomes 0, then a c q u i r e acquire acquire has to wait for a process to give way

E v e n t Event Event
He can let a group wait until one or more processes are executed before running
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 ∣) at time t i m e time Before or e . i s _ s e t ( ) e.is\_set() e.is_set() becomes T r u e True Wait until True

e . s e t ( ) e.set() e.set() enable e . i s _ s e t ( ) e.is\_set() e.is_set() becomes 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() becomes F a l s e False False

I used the above two to write a very interesting car crossing the road( E v e n t Event Event control)
There are two lights. The car can pass only when they turn green. The red light of the two lights can only wait one at a time
( S e m a p h o r e Semaphore Semaphore control)

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()  # Wait for the green light
    print("green, {} go go go".format(car_name))


if __name__ == "__main__":
    ss = multiprocessing.Semaphore(1)  # The lights can only change one at a time
    ee = multiprocessing.Event()
    cars = []

    for i in range(1, 6):  # Six cars
        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  # Judge whether it's all over
        if num == 0:
            ee.set()
            print("all lights are green\n")
            break
    try:
        while True:  # Monitor every second to see if all the cars have passed
            flag = 1
            for i in cars:
                if i.is_alive():
                    flag = 0
            if flag == 0:
                time.sleep(1)
                exit(0)
    except KeyboardInterrupt:
        print("Manual block")
    except UnboundLocalError:
        print("Variable unnamed")
    finally:
        print("all car across")

result

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

Provide a queue that can be accessed by all processes
p u t put put method
To insert data into the queue, the put method also has two optional parameters: b l o c k e d blocked blocked and t i m e o u t timeout timeout.
If b l o c k e d blocked blocked is T r u e True True (default), and t i m e o u t timeout If timeout is positive, the method blocks t i m e o u t timeout timeout the specified time until the queue has free space. If it times out, it will be thrown Q u e u e . F u l l Queue.Full Queue.Full exception.
If b l o c k e d blocked blocked is F a l s e False False, but the Q u e u e Queue If the Queue is full, it will be thrown immediately Q u e u e . F u l l Queue.Full Queue.Full exception.

g e t get get method
Reads and deletes an element from the queue. Again, g e t get The get method has two optional parameters: b l o c k e d blocked blocked and t i m e o u t timeout timeout.
If b l o c k e d blocked blocked is T r u e True True (default), and t i m e o u t timeout If timeout is a positive value, if no element is retrieved during the waiting time, an error will be thrown Q u e u e . E m p t y Queue.Empty Queue.Empty exception.
If b l o c k e d blocked blocked is F a l s e False False, there are two situations, if Q u e u e Queue If the Queue has a value available, the value is returned immediately. Otherwise, if the Queue is empty, it is thrown immediately Q u e u e . E m p t y Queue.Empty Queue.Empty exception.
Event is used to ensure that all data are inserted and then retrieved

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

result

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

If you don't use it, it seems to coo

Pool

Feeling and S e m a p h o r e Semaphore Semaphore is a bit like, you can choose asynchronous and parallel steps
a p p l y , a s y n c apply,_async apply,a​sync ( f u n c , a r g s ) (func, args) (func,args) it is non blocking
His return value needs to be written c a l l b a c k callback callback parameter
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 , ( element group ) , c a l l b a c k = o u t ) pool1.apply\_async(print\_time, (tuple), callback=out) pool1.apply_async(print_time, (tuple), callback=out)
p r i n t _ t i m e print\_time print_time and o u t out out is a function, o u t out The function parameter of out is p r i n t _ t i m e print\_time print_ Return value of time

a p p l y apply apply ( f u n c , a r g s ) (func, args) (func,args) is blocked, and the return value is directly the return value after the process runs

c l o s e ( ) close() close() close p o o l pool pool so that it is no longer accepting new tasks.

t e r m i n a t e ( ) terminate() terminate() ends the work process and does not process unfinished tasks.

j o i n ( ) join() join() the main process is blocked and waits for the child process to exit,
j o i n join The join method should be c l o s e close close or t e r m i n a t e terminate Use after 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)

Decorator

Divided into with and without parameters
Class decorators and function decorators

Function decorator without parameters

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()

Decorator with parameters (decorating function)

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("I'm special")
        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)

Class decorator
Mainly through internal__ c a l l call call__ method

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)

Posted by Spoiler on Thu, 18 Nov 2021 23:03:02 -0800