首页 > 编程语言 >python并发与并行(六) ———— 正确的重构代码,以便用Queue做并发

python并发与并行(六) ———— 正确的重构代码,以便用Queue做并发

时间:2024-08-31 13:52:53浏览次数:12  
标签:opt python photo py Queue 并发 python3.9 calc 0.000


在前面“python并发与并行(五.2) ———— 不要在每次fan-out时都新建一批Thread实例”里面,大家看到,每次都手工创建一批线程并平行地执行I/O任务是有很多缺点的。 这一条要介绍另一种方案,也就是用内置的queue模块里的Queue类实现多线程管道。

Queue方案的总思路是:在推进游戏时,不像原来那样,每推进一代,就新建一批线程来推进相应的单元格,而是可以提前创建数量固定的一组工作线程,令这组线程平行地处理当前这批I/O任务,并在处理完之后,继续等待下一批任务,这样就不会消耗那么多资源了,程序也不会再因为频繁新建线程而耽误那么多时间。

首先,创建两个ClosableQueue实例表示输入队列(in_queue)与输出队列(out_queue)。每条工作线程都可以从输入队列里面取出有待执行的game_logic任务,并把执行结果放到输出队列之中。

from queue import Queue

class ClosableQueue(Queue):
    # 定义哨兵对象
    # 哨兵(SENTINEL)是一个唯一的对象,用于作为队列关闭的信号。
    # 哨兵对象是不可变的,并且是唯一的,这意味着在程序中不会有其他对象与之相同。
    SENTINEL = object()

    # close 方法将哨兵对象放入队列中。当线程从队列中取出哨兵对象时,
    # 它会识别出队列已被关闭,并可以采取适当的行动,比如退出循环或终止线程。
    def close(self):
        self.put(self.SENTINEL)

    def __iter__(self):
        while True:
            item = self.get()
            try:
                if item is self.SENTINEL:
                    return  # Cause the thread to exit
                yield item
            finally:
                # task_done 方法用于通知队列某个任务已经处理完成,
                # 这对于队列的消费者线程是必要的,以确保队列知道何时所有项目都已被处理。
                self.task_done()

in_queue = ClosableQueue()
out_queue = ClosableQueue()

使用 ClosableQueue 类可以方便地在多线程环境中控制数据流,当主线程决定不再处理数据时,可以通过调用 close 方法来通知工作线程停止处理并安全退出。这种模式在生产者-消费者问题中特别有用。

然后我们启动多线程从in_queue里面获取任务,并调用game_logic来处理各自的任务,然后把结果放到out_queue里面。这些线程会并发地运行,从而平行地处理这些I/O任务,以降低游戏进入下一代时的延迟。

from threading import Thread

class StoppableWorker(Thread):
    def __init__(self, func, in_queue, out_queue, **kwargs):
        super().__init__(**kwargs)
        self.func = func
        self.in_queue = in_queue
        self.out_queue = out_queue

    def run(self):
        for item in self.in_queue:
            result = self.func(item)
            self.out_queue.put(result)

# def game_logic(state, neighbors):
#     # Do some blocking input/output in here:
#     data = my_socket.recv(100)
ALIVE = '*'
EMPTY = '-'
def game_logic(state, neighbors):
    if state == ALIVE:
        if neighbors < 2:
            return EMPTY     # Die: Too few
        elif neighbors > 3:
            return EMPTY     # Die: Too many
    else:
        if neighbors == 3:
            return ALIVE     # Regenerate
    return state

def game_logic_thread(item):
    y, x, state, neighbors = item
    try:
        next_state = game_logic(state, neighbors)
    except Exception as e:
        next_state = e
    return (y, x, next_state)

# Start the threads upfront
threads = []
for _ in range(5):
    thread = StoppableWorker(
        game_logic_thread, in_queue, out_queue)
    thread.start()
    threads.append(thread)

simulate函数需要重构。这次,它必须与刚才的两个队列交互,把需要迁移的每一个单元格及其当前状态都封装成一项任务放到输入队列之中,并等待那些线程把输入队列中的所有任务都处理完,接下来,它要根据输出队列所收集到的结果更新每个单元格的状态,从而将游戏推进到下一代。把迁移单元格状态的任务放到输入队列,派发给工作线程去执行,这里用的是fan-out(扇出)模式;等待这些任务全都处理完毕,然后才开始使用输出队列所收集到的结果,这里用的是fan-in(扇入)模式。

class SimulationError(Exception):
    pass

class Grid:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.rows = []
        for _ in range(self.height):
            self.rows.append([EMPTY] * self.width)

    def get(self, y, x):
        return self.rows[y % self.height][x % self.width]

    def set(self, y, x, state):
        self.rows[y % self.height][x % self.width] = state

    def __str__(self):
        output = ''
        for row in self.rows:
            for cell in row:
                output += cell
            output += '\n'
        return output

def count_neighbors(y, x, get):
    n_ = get(y - 1, x + 0)  # North
    ne = get(y - 1, x + 1)  # Northeast
    e_ = get(y + 0, x + 1)  # East
    se = get(y + 1, x + 1)  # Southeast
    s_ = get(y + 1, x + 0)  # South
    sw = get(y + 1, x - 1)  # Southwest
    w_ = get(y + 0, x - 1)  # West
    nw = get(y - 1, x - 1)  # Northwest
    neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]
    count = 0
    for state in neighbor_states:
        if state == ALIVE:
            count += 1
    return count

def simulate_pipeline(grid, in_queue, out_queue):
    for y in range(grid.height):
        for x in range(grid.width):
            state = grid.get(y, x)
            neighbors = count_neighbors(y, x, grid.get)
            in_queue.put((y, x, state, neighbors))  # Fan out

    in_queue.join()
    out_queue.close()

    next_grid = Grid(grid.height, grid.width)
    for item in out_queue:                          # Fan in
        y, x, next_state = item
        if isinstance(next_state, Exception):
            raise SimulationError(y, x) from next_state
        next_grid.set(y, x, next_state)

    return next_grid

新的simulate_pipeline函数要用到网格(Grid)类的get方法与set方法,但它这次是在自身所处的这条线程里面调用这两个方法的,所以不用像上一条那样,专门编写一种支持多线程的网格,并通过Lock机制给这两个方法加锁以防网格之中的数据遭到破坏。我们这次可以直接使用普通版的Grid类。

完整的代码如下:

import logging
from queue import Queue

class ClosableQueue(Queue):
    SENTINEL = object()

    def close(self):
        self.put(self.SENTINEL)

    def __iter__(self):
        while True:
            item = self.get()
            try:
                if item is self.SENTINEL:
                    return  # Cause the thread to exit
                yield item
            finally:
                self.task_done()

in_queue = ClosableQueue()
out_queue = ClosableQueue()


from threading import Thread

class StoppableWorker(Thread):
    def __init__(self, func, in_queue, out_queue, **kwargs):
        super().__init__(**kwargs)
        self.func = func
        self.in_queue = in_queue
        self.out_queue = out_queue

    def run(self):
        for item in self.in_queue:
            result = self.func(item)
            self.out_queue.put(result)

# def game_logic(state, neighbors):
#     # Do some blocking input/output in here:
#     data = my_socket.recv(100)

ALIVE = '*'
EMPTY = '-'
def game_logic(state, neighbors):
    if state == ALIVE:
        if neighbors < 2:
            return EMPTY     # Die: Too few
        elif neighbors > 3:
            return EMPTY     # Die: Too many
    else:
        if neighbors == 3:
            return ALIVE     # Regenerate
    return state

def game_logic_thread(item):
    y, x, state, neighbors = item
    try:
        next_state = game_logic(state, neighbors)
    except Exception as e:
        next_state = e
    return (y, x, next_state)

# Start the threads upfront

threads = []
for _ in range(5):
    thread = StoppableWorker(
        game_logic_thread, in_queue, out_queue)
    thread.start()
    threads.append(thread)


class SimulationError(Exception):
    pass

class Grid:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.rows = []
        for _ in range(self.height):
            self.rows.append([EMPTY] * self.width)

    def get(self, y, x):
        return self.rows[y % self.height][x % self.width]

    def set(self, y, x, state):
        self.rows[y % self.height][x % self.width] = state

    def __str__(self):
        output = ''
        for row in self.rows:
            for cell in row:
                output += cell
            output += '\n'
        return output

def count_neighbors(y, x, get):
    n_ = get(y - 1, x + 0)  # North
    ne = get(y - 1, x + 1)  # Northeast
    e_ = get(y + 0, x + 1)  # East
    se = get(y + 1, x + 1)  # Southeast
    s_ = get(y + 1, x + 0)  # South
    sw = get(y + 1, x - 1)  # Southwest
    w_ = get(y + 0, x - 1)  # West
    nw = get(y - 1, x - 1)  # Northwest
    neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]
    count = 0
    for state in neighbor_states:
        if state == ALIVE:
            count += 1
    return count

def simulate_pipeline(grid, in_queue, out_queue):
    for y in range(grid.height):
        for x in range(grid.width):
            state = grid.get(y, x)
            neighbors = count_neighbors(y, x, grid.get)
            in_queue.put((y, x, state, neighbors))  # Fan out

    in_queue.join()
    out_queue.close()

    next_grid = Grid(grid.height, grid.width)
    for item in out_queue:                          # Fan in
        y, x, next_state = item
        if isinstance(next_state, Exception):
            raise SimulationError(y, x) from next_state
        next_grid.set(y, x, next_state)

    return next_grid


# try:
#     def game_logic(state, neighbors):
#         raise OSError('Problem with I/O in game_logic')
#
#
#     simulate_pipeline(Grid(1, 1), in_queue, out_queue)
# except:
#     logging.exception('Expected')
# else:
#     assert False


class ColumnPrinter:
    def __init__(self):
        self.columns = []

    def append(self, data):
        self.columns.append(data)

    def __str__(self):
        row_count = 1
        for data in self.columns:
            row_count = max(
                row_count, len(data.splitlines()) + 1)

        rows = [''] * row_count
        for j in range(row_count):
            for i, data in enumerate(self.columns):
                line = data.splitlines()[max(0, j - 1)]
                if j == 0:
                    padding = ' ' * (len(line) // 2)
                    rows[j] += padding + str(i) + padding
                else:
                    rows[j] += line

                if (i + 1) < len(self.columns):
                    rows[j] += ' | '

        return '\n'.join(rows)

grid = Grid(5, 9)
grid.set(0, 3, ALIVE)
grid.set(1, 4, ALIVE)
grid.set(2, 2, ALIVE)
grid.set(2, 3, ALIVE)
grid.set(2, 4, ALIVE)

columns = ColumnPrinter()
for i in range(5):
    columns.append(str(grid))
    grid = simulate_pipeline(grid, in_queue, out_queue)

print(columns)

for thread in threads:
    in_queue.close()
for thread in threads:
    thread.join()

现在的代码要比那种每次都手工新建一批线程的方案更容易调试。如果game_logic函数执行I/O时出错,那么错误会被捕获并传入输出队列里面,并在主线程之中重新抛出。

这样写的效果和原来一样。与那种每次操作都启动一条线程的做法相比,这种方案使用的内存少,启动线程时的开销也小,而且调试起来较为容易。尽管如此,但它还是有几个问题:

负责把网格推进到下一代的simulate_pipeline函数,要比上一条里面的对应函数simulate_threaded难懂

为了让代码更容易理解,必须用ClosableQueue与StoppableWorker这样的类表示特制的队列与工作线程,这会让程序变得复杂。

与并行度有关的那个参数(即运行game_logic_thread函数的线程数量),必须依工作负载提前定好,而无法由系统根据工作量自动调整。

我们同样像前几节那样,把Grid的大小改为(50,90),然后迭代100次,看一下性能。

主要是修改如下的地方:

grid = Grid(50, 90)
grid.set(0, 3, ALIVE)
grid.set(1, 4, ALIVE)
grid.set(2, 2, ALIVE)
grid.set(2, 3, ALIVE)
grid.set(2, 4, ALIVE)

columns = ColumnPrinter()
import time
st=time.time()
for i in range(100):
    columns.append(str(grid))
    grid = simulate_pipeline(grid, in_queue, out_queue)

print(f'::LOG::simulation time: {time.time() - st}')

全部的代码如下:

import logging
from queue import Queue

class ClosableQueue(Queue):
    SENTINEL = object()

    def close(self):
        self.put(self.SENTINEL)

    def __iter__(self):
        while True:
            item = self.get()
            try:
                if item is self.SENTINEL:
                    return  # Cause the thread to exit
                yield item
            finally:
                self.task_done()

in_queue = ClosableQueue()
out_queue = ClosableQueue()


from threading import Thread

class StoppableWorker(Thread):
    def __init__(self, func, in_queue, out_queue, **kwargs):
        super().__init__(**kwargs)
        self.func = func
        self.in_queue = in_queue
        self.out_queue = out_queue

    def run(self):
        for item in self.in_queue:
            result = self.func(item)
            self.out_queue.put(result)

# def game_logic(state, neighbors):
#     # Do some blocking input/output in here:
#     data = my_socket.recv(100)

ALIVE = '*'
EMPTY = '-'
def game_logic(state, neighbors):
    if state == ALIVE:
        if neighbors < 2:
            return EMPTY     # Die: Too few
        elif neighbors > 3:
            return EMPTY     # Die: Too many
    else:
        if neighbors == 3:
            return ALIVE     # Regenerate
    return state

def game_logic_thread(item):
    y, x, state, neighbors = item
    try:
        next_state = game_logic(state, neighbors)
    except Exception as e:
        next_state = e
    return (y, x, next_state)

# Start the threads upfront

threads = []
for _ in range(5):
    thread = StoppableWorker(
        game_logic_thread, in_queue, out_queue)
    thread.start()
    threads.append(thread)


class SimulationError(Exception):
    pass

class Grid:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.rows = []
        for _ in range(self.height):
            self.rows.append([EMPTY] * self.width)

    def get(self, y, x):
        return self.rows[y % self.height][x % self.width]

    def set(self, y, x, state):
        self.rows[y % self.height][x % self.width] = state

    def __str__(self):
        output = ''
        for row in self.rows:
            for cell in row:
                output += cell
            output += '\n'
        return output

def count_neighbors(y, x, get):
    n_ = get(y - 1, x + 0)  # North
    ne = get(y - 1, x + 1)  # Northeast
    e_ = get(y + 0, x + 1)  # East
    se = get(y + 1, x + 1)  # Southeast
    s_ = get(y + 1, x + 0)  # South
    sw = get(y + 1, x - 1)  # Southwest
    w_ = get(y + 0, x - 1)  # West
    nw = get(y - 1, x - 1)  # Northwest
    neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]
    count = 0
    for state in neighbor_states:
        if state == ALIVE:
            count += 1
    return count

def simulate_pipeline(grid, in_queue, out_queue):
    for y in range(grid.height):
        for x in range(grid.width):
            state = grid.get(y, x)
            neighbors = count_neighbors(y, x, grid.get)
            in_queue.put((y, x, state, neighbors))  # Fan out

    in_queue.join()
    out_queue.close()

    next_grid = Grid(grid.height, grid.width)
    for item in out_queue:                          # Fan in
        y, x, next_state = item
        if isinstance(next_state, Exception):
            raise SimulationError(y, x) from next_state
        next_grid.set(y, x, next_state)

    return next_grid


# try:
#     def game_logic(state, neighbors):
#         raise OSError('Problem with I/O in game_logic')
#
#
#     simulate_pipeline(Grid(1, 1), in_queue, out_queue)
# except:
#     logging.exception('Expected')
# else:
#     assert False


class ColumnPrinter:
    def __init__(self):
        self.columns = []

    def append(self, data):
        self.columns.append(data)

    def __str__(self):
        row_count = 1
        for data in self.columns:
            row_count = max(
                row_count, len(data.splitlines()) + 1)

        rows = [''] * row_count
        for j in range(row_count):
            for i, data in enumerate(self.columns):
                line = data.splitlines()[max(0, j - 1)]
                if j == 0:
                    padding = ' ' * (len(line) // 2)
                    rows[j] += padding + str(i) + padding
                else:
                    rows[j] += line

                if (i + 1) < len(self.columns):
                    rows[j] += ' | '

        return '\n'.join(rows)

grid = Grid(50, 90)
grid.set(0, 3, ALIVE)
grid.set(1, 4, ALIVE)
grid.set(2, 2, ALIVE)
grid.set(2, 3, ALIVE)
grid.set(2, 4, ALIVE)

columns = ColumnPrinter()
import time
st=time.time()
for i in range(100):
    columns.append(str(grid))
    grid = simulate_pipeline(grid, in_queue, out_queue)

print(f'::LOG::simulation time: {time.time() - st}')

print(columns)

for thread in threads:
    in_queue.close()
for thread in threads:
    thread.join()

Output:

::LOG::simulation time: 2.5422348976135254

我们从前一节得知,前一节实现的多线程 simulation time: 14.29249095916748 单线程 simulate time: 0.6782510280609131。

我们本节的实现虽然比前一节的多线程版本有较大的性能提升,但是仍然还不如单线程的版本。

threads = []
for _ in range(10):
    thread = StoppableWorker(
        game_logic_thread, in_queue, out_queue)
    thread.start()
    threads.append(thread)

如上面,我们把总的线程增加到10个,::LOG::simulation time: 3.507694721221924

我们把线程数设为1个,::LOG::simulation time: 2.471439838409424

我们把线程数设为20个,::LOG::simulation time: 3.195152759552002

如果我们把Grid设置为(500,900),迭代次数为100次,线程数设为5,我们看一下耗时。

grid = Grid(500, 900)
grid.set(0, 3, ALIVE)
grid.set(1, 4, ALIVE)
grid.set(2, 2, ALIVE)
grid.set(2, 3, ALIVE)
grid.set(2, 4, ALIVE)

columns = ColumnPrinter()
import time
from tqdm import tqdm
st=time.time()

for i in tqdm(range(100)):
    columns.append(str(grid))
    grid = simulate_pipeline(grid, in_queue, out_queue)

print(f'::LOG::simulation time: {time.time() - st}')

::LOG::simulation time: 170.44810271263123

我们把前面的单线程的程序,用同样的规格跑一下。

ALIVE = '*'
EMPTY = '-'

class Grid:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.rows = []
        for _ in range(self.height):
            self.rows.append([EMPTY] * self.width)

    def get(self, y, x):
        return self.rows[y % self.height][x % self.width]

    def set(self, y, x, state):
        self.rows[y % self.height][x % self.width] = state

    def __str__(self):
        output = ''
        for row in self.rows:
            for cell in row:
                output += cell
            output += '\n'
        return output


grid = Grid(500, 900)
grid.set(0, 3, ALIVE)
grid.set(1, 4, ALIVE)
grid.set(2, 2, ALIVE)
grid.set(2, 3, ALIVE)
grid.set(2, 4, ALIVE)
print(grid)


def count_neighbors(y, x, get):
    n_ = get(y - 1, x + 0)  # North
    ne = get(y - 1, x + 1)  # Northeast
    e_ = get(y + 0, x + 1)  # East
    se = get(y + 1, x + 1)  # Southeast
    s_ = get(y + 1, x + 0)  # South
    sw = get(y + 1, x - 1)  # Southwest
    w_ = get(y + 0, x - 1)  # West
    nw = get(y - 1, x - 1)  # Northwest
    neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]
    count = 0
    for state in neighbor_states:
        if state == ALIVE:
            count += 1
    return count

alive = {(9, 5), (9, 6)}
seen = set()

def fake_get(y, x):
    position = (y, x)
    seen.add(position)
    return ALIVE if position in alive else EMPTY

count = count_neighbors(10, 5, fake_get)
assert count == 2

expected_seen = {
    (9, 5),  (9, 6),  (10, 6), (11, 6),
    (11, 5), (11, 4), (10, 4), (9, 4)
}
assert seen == expected_seen


def game_logic(state, neighbors):
    if state == ALIVE:
        if neighbors < 2:
            return EMPTY     # Die: Too few
        elif neighbors > 3:
            return EMPTY     # Die: Too many
    else:
        if neighbors == 3:
            return ALIVE     # Regenerate
    return state

assert game_logic(ALIVE, 0) == EMPTY
assert game_logic(ALIVE, 1) == EMPTY
assert game_logic(ALIVE, 2) == ALIVE
assert game_logic(ALIVE, 3) == ALIVE
assert game_logic(ALIVE, 4) == EMPTY
assert game_logic(EMPTY, 0) == EMPTY
assert game_logic(EMPTY, 1) == EMPTY
assert game_logic(EMPTY, 2) == EMPTY
assert game_logic(EMPTY, 3) == ALIVE
assert game_logic(EMPTY, 4) == EMPTY


def step_cell(y, x, get, set):
    state = get(y, x)
    neighbors = count_neighbors(y, x, get)
    next_state = game_logic(state, neighbors)
    set(y, x, next_state)

alive = {(10, 5), (9, 5), (9, 6)}
new_state = None

def fake_get(y, x):
    return ALIVE if (y, x) in alive else EMPTY

def fake_set(y, x, state):
    global new_state
    new_state = state

# Stay alive
step_cell(10, 5, fake_get, fake_set)
assert new_state == ALIVE

# Stay dead
alive.remove((10, 5))
step_cell(10, 5, fake_get, fake_set)
assert new_state == EMPTY

# Regenerate
alive.add((10, 6))
step_cell(10, 5, fake_get, fake_set)
assert new_state == ALIVE


def simulate(grid):
    next_grid = Grid(grid.height, grid.width)
    for y in range(grid.height):
        for x in range(grid.width):
            step_cell(y, x, grid.get, next_grid.set)
    return next_grid


class ColumnPrinter:
    def __init__(self):
        self.columns = []

    def append(self, data):
        self.columns.append(data)

    def __str__(self):
        row_count = 1
        for data in self.columns:
            row_count = max(
                row_count, len(data.splitlines()) + 1)

        rows = [''] * row_count
        for j in range(row_count):
            for i, data in enumerate(self.columns):
                line = data.splitlines()[max(0, j - 1)]
                if j == 0:
                    padding = ' ' * (len(line) // 2)
                    rows[j] += padding + str(i) + padding
                else:
                    rows[j] += line

                if (i + 1) < len(self.columns):
                    rows[j] += ' | '

        return '\n'.join(rows)

columns = ColumnPrinter()
import time
st=time.time()
from tqdm import tqdm
for i in tqdm(range(100)):
    columns.append(str(grid))
    grid = simulate(grid)
print(f'simulate time: {time.time() - st}')
# print(columns)

simulate time: 55.45792198181152

我们继续把Grid大小设置为(900,1200),看一下对比。

本节实现的多线程:simulation time: 419.4681279659271
单线程:simulate time: 137.2363736629486

多线程的性能仍然不如单线程。我们还使用上一节的cProfile对多线程的代码进行一下profiling,看一下性能瓶颈在什么地方。

对代码做一下修改,将run simulation的部分封装为函数。

import cProfile
import pstats

def run_simulation():
    grid = Grid(50, 90)
    grid.set(0, 3, ALIVE)
    grid.set(1, 4, ALIVE)
    grid.set(2, 2, ALIVE)
    grid.set(2, 3, ALIVE)
    grid.set(2, 4, ALIVE)

    columns = ColumnPrinter()
    import time
    from tqdm import tqdm
    st=time.time()

    for i in tqdm(range(100)):
        columns.append(str(grid))
        grid = simulate_pipeline(grid, in_queue, out_queue)

    print(f'::LOG::simulation time: {time.time() - st}')

cProfile.run('run_simulation()','threaded_prof')
with open('threaded_profile.txt', 'w') as f:
    p = pstats.Stats('threaded_prof', stream=f)
    p.sort_stats('cumulative').print_stats()

print("Profile saved to 'threaded_profile.txt'")

完整代码为:

import logging
from queue import Queue

class ClosableQueue(Queue):
    SENTINEL = object()

    def close(self):
        self.put(self.SENTINEL)

    def __iter__(self):
        while True:
            item = self.get()
            try:
                if item is self.SENTINEL:
                    return  # Cause the thread to exit
                yield item
            finally:
                self.task_done()

in_queue = ClosableQueue()
out_queue = ClosableQueue()


from threading import Thread

class StoppableWorker(Thread):
    def __init__(self, func, in_queue, out_queue, **kwargs):
        super().__init__(**kwargs)
        self.func = func
        self.in_queue = in_queue
        self.out_queue = out_queue

    def run(self):
        for item in self.in_queue:
            result = self.func(item)
            self.out_queue.put(result)

# def game_logic(state, neighbors):
#     # Do some blocking input/output in here:
#     data = my_socket.recv(100)

ALIVE = '*'
EMPTY = '-'
def game_logic(state, neighbors):
    if state == ALIVE:
        if neighbors < 2:
            return EMPTY     # Die: Too few
        elif neighbors > 3:
            return EMPTY     # Die: Too many
    else:
        if neighbors == 3:
            return ALIVE     # Regenerate
    return state

def game_logic_thread(item):
    y, x, state, neighbors = item
    try:
        next_state = game_logic(state, neighbors)
    except Exception as e:
        next_state = e
    return (y, x, next_state)

# Start the threads upfront

threads = []
for _ in range(10):
    thread = StoppableWorker(
        game_logic_thread, in_queue, out_queue)
    thread.start()
    threads.append(thread)


class SimulationError(Exception):
    pass

class Grid:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.rows = []
        for _ in range(self.height):
            self.rows.append([EMPTY] * self.width)

    def get(self, y, x):
        return self.rows[y % self.height][x % self.width]

    def set(self, y, x, state):
        self.rows[y % self.height][x % self.width] = state

    def __str__(self):
        output = ''
        for row in self.rows:
            for cell in row:
                output += cell
            output += '\n'
        return output

def count_neighbors(y, x, get):
    n_ = get(y - 1, x + 0)  # North
    ne = get(y - 1, x + 1)  # Northeast
    e_ = get(y + 0, x + 1)  # East
    se = get(y + 1, x + 1)  # Southeast
    s_ = get(y + 1, x + 0)  # South
    sw = get(y + 1, x - 1)  # Southwest
    w_ = get(y + 0, x - 1)  # West
    nw = get(y - 1, x - 1)  # Northwest
    neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]
    count = 0
    for state in neighbor_states:
        if state == ALIVE:
            count += 1
    return count

def simulate_pipeline(grid, in_queue, out_queue):
    for y in range(grid.height):
        for x in range(grid.width):
            state = grid.get(y, x)
            neighbors = count_neighbors(y, x, grid.get)
            in_queue.put((y, x, state, neighbors))  # Fan out

    in_queue.join()
    out_queue.close()

    next_grid = Grid(grid.height, grid.width)
    for item in out_queue:                          # Fan in
        y, x, next_state = item
        if isinstance(next_state, Exception):
            raise SimulationError(y, x) from next_state
        next_grid.set(y, x, next_state)

    return next_grid


# try:
#     def game_logic(state, neighbors):
#         raise OSError('Problem with I/O in game_logic')
#
#
#     simulate_pipeline(Grid(1, 1), in_queue, out_queue)
# except:
#     logging.exception('Expected')
# else:
#     assert False


class ColumnPrinter:
    def __init__(self):
        self.columns = []

    def append(self, data):
        self.columns.append(data)

    def __str__(self):
        row_count = 1
        for data in self.columns:
            row_count = max(
                row_count, len(data.splitlines()) + 1)

        rows = [''] * row_count
        for j in range(row_count):
            for i, data in enumerate(self.columns):
                line = data.splitlines()[max(0, j - 1)]
                if j == 0:
                    padding = ' ' * (len(line) // 2)
                    rows[j] += padding + str(i) + padding
                else:
                    rows[j] += line

                if (i + 1) < len(self.columns):
                    rows[j] += ' | '

        return '\n'.join(rows)


import cProfile
import pstats

def run_simulation():
    grid = Grid(50, 90)
    grid.set(0, 3, ALIVE)
    grid.set(1, 4, ALIVE)
    grid.set(2, 2, ALIVE)
    grid.set(2, 3, ALIVE)
    grid.set(2, 4, ALIVE)

    columns = ColumnPrinter()
    import time
    from tqdm import tqdm
    st=time.time()

    for i in tqdm(range(100)):
        columns.append(str(grid))
        grid = simulate_pipeline(grid, in_queue, out_queue)

    print(f'::LOG::simulation time: {time.time() - st}')

cProfile.run('run_simulation()','threaded_prof')
with open('threaded_profile.txt', 'w') as f:
    p = pstats.Stats('threaded_prof', stream=f)
    p.sort_stats('cumulative').print_stats()

print("Profile saved to 'threaded_profile.txt'")

for thread in threads:
    in_queue.close()
for thread in threads:
    thread.join()

结果为:

Fri Aug  9 23:09:25 2024    threaded_prof

         18065587 function calls (18065085 primitive calls) in 3.713 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     39/1    0.000    0.000    3.713    3.713 {built-in method builtins.exec}
        1    0.001    0.001    3.713    3.713 /Users/wenyan/projects2024/efficient_python/test_queue.py:178(run_simulation)
      100    0.226    0.002    3.665    0.037 /Users/wenyan/projects2024/efficient_python/test_queue.py:114(simulate_pipeline)
   450100    0.199    0.000    1.428    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:122(put)
  1350401    0.122    0.000    1.111    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:256(__enter__)
  1350401    0.989    0.000    0.989    0.000 {method '__enter__' of '_thread.lock' objects}
   450100    0.094    0.000    0.853    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:10(__iter__)
   450000    0.380    0.000    0.774    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:98(count_neighbors)
   450100    0.216    0.000    0.540    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:154(get)
  4050000    0.450    0.000    0.450    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:84(get)
   900704    0.313    0.000    0.313    0.000 {method 'acquire' of '_thread.lock' objects}
      100    0.000    0.000    0.269    0.003 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:79(join)
      101    0.000    0.000    0.269    0.003 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:280(wait)
   900300    0.092    0.000    0.222    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:351(notify)
   450100    0.110    0.000    0.220    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:57(task_done)
  1350401    0.123    0.000    0.173    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:259(__exit__)
   900401    0.083    0.000    0.128    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:271(_is_owned)
   450100    0.044    0.000    0.056    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:217(_get)
   450100    0.042    0.000    0.053    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:213(_put)
  1350550    0.050    0.000    0.050    0.000 {method '__exit__' of '_thread.lock' objects}
   450100    0.036    0.000    0.048    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/queue.py:209(_qsize)
   450005    0.043    0.000    0.043    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:87(set)
     64/6    0.000    0.000    0.027    0.005 <frozen importlib._bootstrap>:1002(_find_and_load)
     64/6    0.000    0.000    0.027    0.005 <frozen importlib._bootstrap>:967(_find_and_load_unlocked)
     60/6    0.000    0.000    0.027    0.004 <frozen importlib._bootstrap>:659(_load_unlocked)
     91/8    0.000    0.000    0.026    0.003 <frozen importlib._bootstrap>:220(_call_with_frames_removed)
     38/4    0.000    0.000    0.026    0.006 <frozen importlib._bootstrap_external>:844(exec_module)
        1    0.000    0.000    0.020    0.020 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:663(__new__)
        1    0.000    0.000    0.020    0.020 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:760(get_lock)
        1    0.000    0.000    0.020    0.020 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:90(__init__)
        1    0.000    0.000    0.020    0.020 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:116(create_mp_lock)
      100    0.014    0.000    0.014    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:90(__str__)
   452146    0.014    0.000    0.014    0.000 {built-in method builtins.isinstance}
451152/451107    0.012    0.000    0.012    0.000 {built-in method builtins.len}
        1    0.000    0.000    0.012    0.012 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:70(RLock)
   450100    0.012    0.000    0.012    0.000 {method 'popleft' of 'collections.deque' objects}
     22/9    0.000    0.000    0.011    0.001 <frozen importlib._bootstrap>:1033(_handle_fromlist)
      9/3    0.000    0.000    0.011    0.004 {built-in method builtins.__import__}
   450201    0.011    0.000    0.011    0.000 {method 'append' of 'collections.deque' objects}
       38    0.000    0.000    0.010    0.000 <frozen importlib._bootstrap_external>:916(get_code)
       60    0.000    0.000    0.009    0.000 <frozen importlib._bootstrap>:558(module_from_spec)
       20    0.000    0.000    0.008    0.000 <frozen importlib._bootstrap_external>:1171(create_module)
       20    0.008    0.000    0.008    0.000 {built-in method _imp.create_dynamic}
       38    0.000    0.000    0.008    0.000 <frozen importlib._bootstrap_external>:1036(get_data)
        1    0.000    0.000    0.007    0.007 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/__init__.py:15(<module>)
        1    0.000    0.000    0.007    0.007 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:10(<module>)
        1    0.000    0.000    0.007    0.007 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:1(<module>)
        1    0.000    0.000    0.007    0.007 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/__init__.py:1(<module>)
        1    0.000    0.000    0.006    0.006 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/reduction.py:10(<module>)
        1    0.000    0.000    0.005    0.005 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:1(<module>)
        1    0.000    0.000    0.005    0.005 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/cli.py:1(<module>)
       38    0.005    0.000    0.005    0.000 {method 'read' of '_io.BufferedReader' objects}
        1    0.000    0.000    0.004    0.004 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:186(__init__)
        1    0.000    0.000    0.004    0.004 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:50(__init__)
        1    0.000    0.000    0.004    0.004 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1(<module>)
      101    0.000    0.000    0.004    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1160(__iter__)
       62    0.000    0.000    0.004    0.000 <frozen importlib._bootstrap>:901(_find_spec)
       31    0.000    0.000    0.004    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1325(refresh)
       30    0.000    0.000    0.004    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1198(update)
        1    0.000    0.000    0.003    0.003 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:1(<module>)
       32    0.000    0.000    0.003    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1464(display)
       60    0.000    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:1415(find_spec)
       60    0.000    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:1383(_get_spec)
        1    0.000    0.000    0.003    0.003 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/resource_tracker.py:18(<module>)
      129    0.000    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:1514(find_spec)
       38    0.002    0.000    0.002    0.000 {built-in method io.open_code}
        1    0.000    0.000    0.002    0.002 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:4(<module>)
       32    0.000    0.000    0.002    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1150(__str__)
        1    0.000    0.000    0.002    0.002 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/spawn.py:11(<module>)
        1    0.000    0.000    0.002    0.002 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:1(<module>)
       32    0.000    0.000    0.002    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:464(format_meter)
       38    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:645(_compile_bytecode)
       38    0.002    0.000    0.002    0.000 {built-in method marshal.loads}
        1    0.000    0.000    0.002    0.002 /opt/anaconda3/envs/calc_photo/lib/python3.9/runpy.py:1(<module>)
     1959    0.002    0.000    0.002    0.000 {method 'release' of '_thread.lock' objects}
        1    0.000    0.000    0.002    0.002 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:952(__init__)
      235    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:135(_path_stat)
      235    0.002    0.000    0.002    0.000 {built-in method posix.stat}
       96    0.000    0.000    0.002    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:378(disp_len)
       96    0.000    0.000    0.002    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:374(_text_width)
       96    0.000    0.000    0.001    0.000 {built-in method builtins.sum}
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:333(_screen_shape_linux)
       64    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:154(_path_isfile)
       66    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:145(_path_is_mode_type)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1(<module>)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:1(<module>)
      123    0.001    0.000    0.001    0.000 {built-in method builtins.__build_class__}
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:10(<module>)
      101    0.001    0.000    0.001    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:77(__init__)
       32    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:457(print_status)
    11925    0.001    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:375(<genexpr>)
        7    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:528(_convert_)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:1(<module>)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/util.py:1(<module>)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:10(<module>)
       47    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:358(__call__)
        7    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:475(_create_)
      111    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/re.py:289(_compile)
       32    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:386(disp_trim)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/lzma.py:1(<module>)
        5    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:783(compile)
        4    0.000    0.000    0.001    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/re.py:250(compile)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/resource_tracker.py:145(register)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/resource_tracker.py:153(_send)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:1(<module>)
        1    0.000    0.000    0.001    0.001 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/resource_tracker.py:70(ensure_running)
       60    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:486(_init_module_attrs)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/bz2.py:1(<module>)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:179(__new__)
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:451(fp_write)
       66    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:194(inner)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:1(<module>)
       34    0.000    0.000    0.000    0.000 {method 'write' of '_io.TextIOWrapper' objects}
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1565(_fill_cache)
      605    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:121(_path_join)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:447(spawnv_passfds)
        2    0.000    0.000    0.000    0.000 {built-in method posix.listdir}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:10(<module>)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:944(parse)
    11829    0.000    0.000    0.000    0.000 {built-in method unicodedata.east_asian_width}
     23/5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:436(_parse_sub)
     25/5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:494(_parse)
        1    0.000    0.000    0.000    0.000 {built-in method _posixsubprocess.fork_exec}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pkgutil.py:1(<module>)
      134    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x104813388}
       31    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/abc.py:105(__new__)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:545(<listcomp>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/struct.py:1(<module>)
       76    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:361(cache_from_source)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/_monitor.py:30(__init__)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:622(_code)
       96    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:385(cached)
       64    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:156(__enter__)
     5915    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/version.py:1(<module>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/bisect.py:1(<module>)
      100    0.000    0.000    0.000    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:7(close)
      605    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:123(<listcomp>)
       58    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:491(_get_cached)
       86    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:88(__setitem__)
     45/5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:87(_compile)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:245(tqdm)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:1(<module>)
      119    0.000    0.000    0.000    0.000 {method 'format' of 'str' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:197(<listcomp>)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1265(close)
       74    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:166(_get_module_lock)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/collections/__init__.py:345(namedtuple)
        1    0.000    0.000    0.000    0.000 {built-in method fromtimestamp}
      107    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/re.py:188(match)
      631    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
     1858    0.000    0.000    0.000    0.000 {method 'remove' of 'collections.deque' objects}
       58    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1509(_get_spec)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1077(path_stats)
       64    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:160(__exit__)
       35    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:102(acquire)
       74    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:112(release)
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1446(format_dict)
       63    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:400(format_interval)
       64    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:273(_is_ascii)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/numbers.py:4(<module>)
       76    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:127(_path_split)
      181    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:231(__call__)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:528(__init__)
       35    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:106(release)
       62    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/_distutils_hack/__init__.py:82(find_spec)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:221(<setcomp>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:34(envwrap)
      695    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:231(_verbose_message)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:228(__init__)
      104    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:398(parent)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:73(<dictcomp>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:880(start)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:76(wrap)
      143    0.000    0.000    0.000    0.000 {built-in method builtins.max}
      690    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:3111(signature)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2859(from_callable)
       58    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:696(spec_from_file_location)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2246(_signature_from_callable)
       74    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:87(acquire)
       31    0.000    0.000    0.000    0.000 {built-in method now}
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:186(__format__)
      664    0.000    0.000    0.000    0.000 {built-in method builtins.hasattr}
       12    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:492(__new__)
       35    0.000    0.000    0.000    0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
        3    0.000    0.000    0.000    0.000 {built-in method builtins.eval}
       44    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_collections_abc.py:849(__iter__)
     1109    0.000    0.000    0.000    0.000 {method 'startswith' of 'str' objects}
      121    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:462(__setattr__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:802(__init__)
       96    0.000    0.000    0.000    0.000 {method 'sub' of 're.Pattern' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2152(_signature_from_function)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:67(pthread_sigmask)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:560(_classify_pyc)
      172    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1346(_path_importer_cache)
      100    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:381(notify_all)
     1286    0.000    0.000    0.000    0.000 {method 'rstrip' of 'str' objects}
      121    0.000    0.000    0.000    0.000 {built-in method builtins.setattr}
      114    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:79(_unpack_uint32)
      244    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:878(__exit__)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:164(__prepare__)
       38    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:560(_compile_info)
       64    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:185(cb)
      244    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:165(__getitem__)
      135    0.000    0.000    0.000    0.000 {built-in method time.time}
      244    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:874(__enter__)
       31    0.000    0.000    0.000    0.000 {built-in method _abc._abc_init}
    54/19    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:175(getwidth)
      235    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:78(<lambda>)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:593(_validate_timestamp_pyc)
      237    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:88(<lambda>)
      236    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:83(<lambda>)
      238    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:93(<lambda>)
       64    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:58(__init__)
        3    0.000    0.000    0.000    0.000 {built-in method builtins.dir}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:563(wait)
     1015    0.000    0.000    0.000    0.000 {method 'isupper' of 'str' objects}
       20    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:292(_optimize_charset)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1594(datetime)
       21    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:571(_get_mixins_)
       43    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:674(__getitem__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_compat_pickle.py:9(<module>)
      100    0.000    0.000    0.000    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:150(append)
        4    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:70(<genexpr>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:114(_make_name)
       86    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:44(_is_private)
       20    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1179(exec_module)
        3    0.000    0.000    0.000    0.000 {built-in method builtins.next}
      105    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:255(get)
       35    0.000    0.000    0.000    0.000 {method 'release' of '_multiprocessing.SemLock' objects}
      233    0.000    0.000    0.000    0.000 {built-in method _thread.allocate_lock}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:149(__next__)
       62    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:736(find_spec)
       50    0.000    0.000    0.000    0.000 {method 'update' of 'dict' objects}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:24(_int_to_enum)
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:153(__init__)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:20(_register)
       13    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:97(closegroup)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:117(__init__)
      380    0.000    0.000    0.000    0.000 {method 'rpartition' of 'str' objects}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1286(fp_write)
      152    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:129(<genexpr>)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:126(seed)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:186(__init__)
       28    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2498(__init__)
      101    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:268(_acquire_restore)
      165    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:234(__next)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_compression.py:1(<module>)
       21    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:582(_find_data_type)
      101    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:265(_release_save)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1333(_path_hooks)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:44(_get_exports_list)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:686(_decr_instances)
       27    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/abc.py:110(register)
       38    0.000    0.000    0.000    0.000 {built-in method _imp._fix_co_filename}
       10    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:203(_lock_unlock_module)
      695    0.000    0.000    0.000    0.000 {built-in method builtins.ord}
        2    0.000    0.000    0.000    0.000 {function Random.seed at 0x10510e5e0}
      129    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:64(_relax_case)
       69    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:9(<lambda>)
       72    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:12(_is_descriptor)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:618(_find_new_)
       27    0.000    0.000    0.000    0.000 {built-in method _abc._abc_register}
      382    0.000    0.000    0.000    0.000 {built-in method _imp.release_lock}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/_monitor.py:1(<module>)
      382    0.000    0.000    0.000    0.000 {built-in method _imp.acquire_lock}
        1    0.000    0.000    0.000    0.000 {built-in method _thread.start_new_thread}
       86    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:22(_is_dunder)
      205    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:138(rng)
       86    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:33(_is_sunder)
       62    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:351(__init__)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:523(_check_name_wrapper)
       60    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:811(find_spec)
      104    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:250(match)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:213(__init__)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:35(update_wrapper)
       27    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/abc.py:121(__subclasscheck__)
       20    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1155(__init__)
       20    0.000    0.000    0.000    0.000 {built-in method _imp.exec_dynamic}
       86    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:758(decode)
       43    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:754(encode)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1606(path_hook_for_FileFinder)
       44    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:697(__iter__)
        7    0.000    0.000    0.000    0.000 {method 'sort' of 'list' objects}
       19    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:356(_escape)
      218    0.000    0.000    0.000    0.000 {built-in method builtins.divmod}
       20    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:265(_compile_charset)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:63(__iter__)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/contextlib.py:234(contextmanager)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:765(exec_module)
       40    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:670(__new__)
       19    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:447(_simple)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:679(_get_free_pos)
       85    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:161(__len__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:393(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/gui.py:1(<module>)
      107    0.000    0.000    0.000    0.000 {method 'match' of 're.Pattern' objects}
       45    0.000    0.000    0.000    0.000 {built-in method _imp.is_builtin}
       27    0.000    0.000    0.000    0.000 {built-in method _abc._abc_subclasscheck}
        4    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:110(__enter__)
       66    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:287(tell)
        2    0.000    0.000    0.000    0.000 {built-in method _imp.exec_builtin}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2781(__init__)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:977(__and__)
        1    0.000    0.000    0.000    0.000 {built-in method posix.getcwd}
        4    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:113(__exit__)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:86(add)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:1136(_Unpickler)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:2216(timezone)
       13    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:85(opengroup)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:2034(getLogger)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:35(_new_module)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1602(__new__)
        1    0.000    0.000    0.000    0.000 {built-in method posix.urandom}
       64    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:152(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/fnmatch.py:1(<module>)
       54    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:173(append)
       91    0.000    0.000    0.000    0.000 {built-in method builtins.min}
       78    0.000    0.000    0.000    0.000 {method 'endswith' of 'str' objects}
       34    0.000    0.000    0.000    0.000 {method 'flush' of '_io.TextIOWrapper' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:152(<listcomp>)
      149    0.000    0.000    0.000    0.000 {built-in method _thread.get_ident}
        1    0.000    0.000    0.000    0.000 {built-in method fcntl.ioctl}
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1475(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:1284(getLogger)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1594(<setcomp>)
       45    0.000    0.000    0.000    0.000 {built-in method builtins.locals}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:1229(_make_invoke_excepthook)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:682(<setcomp>)
       35    0.000    0.000    0.000    0.000 {method 'add' of 'set' objects}
       38    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/__init__.py:23(<genexpr>)
       78    0.000    0.000    0.000    0.000 {method 'rfind' of 'str' objects}
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:757(create_module)
        8    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:343(choice)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:665(__neg__)
      130    0.000    0.000    0.000    0.000 {built-in method builtins.abs}
      114    0.000    0.000    0.000    0.000 {built-in method from_bytes}
       22    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:175(_path_isabs)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:108(__init__)
       45    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:112(__init__)
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:167(colour)
        2    0.000    0.000    0.000    0.000 <frozen zipimport>:63(__init__)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:561(_check_for_existing_members)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:799(singledispatch)
       10    0.000    0.000    0.000    0.000 {built-in method builtins.any}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:111(remove)
      138    0.000    0.000    0.000    0.000 {built-in method posix.fspath}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/typing.py:1192(__init_subclass__)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:27(__exit__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/__init__.py:22(<listcomp>)
        2    0.000    0.000    0.000    0.000 {built-in method _imp.create_builtin}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/posixpath.py:373(abspath)
      122    0.000    0.000    0.000    0.000 {method 'get' of 'mappingproxy' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:48(<listcomp>)
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:112(__format__)
       74    0.000    0.000    0.000    0.000 {method 'pop' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {built-in method posix.write}
       74    0.000    0.000    0.000    0.000 {built-in method builtins.issubclass}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:843(register)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:415(_check_date_fields)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:225(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:392(__get__)
       37    0.000    0.000    0.000    0.000 {method 'release' of '_thread.RLock' objects}
       60    0.000    0.000    0.000    0.000 {built-in method _imp.is_frozen}
       37    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:82(groups)
       63    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/abc.py:7(abstractmethod)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1006(__init__)
       86    0.000    0.000    0.000    0.000 {method 'decode' of 'bytes' objects}
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:197(<dictcomp>)
        8    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:237(_randbelow_with_getrandbits)
        2    0.000    0.000    0.000    0.000 {built-in method posix.pipe}
        6    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:433(_uniq)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1270(__new__)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:428(_check_time_fields)
       13    0.000    0.000    0.000    0.000 {method 'extend' of 'list' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/numbers.py:32(Complex)
       91    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
       46    0.000    0.000    0.000    0.000 {method 'encode' of 'str' objects}
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:415(spec_from_loader)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:415(__getattr__)
       72    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:551(<lambda>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:700(Popen)
        2    0.000    0.000    0.000    0.000 {built-in method atexit.register}
       37    0.000    0.000    0.000    0.000 {method 'acquire' of '_thread.RLock' objects}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:53(_commit_removals)
       60    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:406(has_location)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:517(decorating_function)
       29    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2830(<genexpr>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:131(Bar)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:823(__new__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:1358(current_thread)
        3    0.000    0.000    0.000    0.000 {method 'remove' of 'set' objects}
       35    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:383(_check_int_field)
       36    0.000    0.000    0.000    0.000 {method 'find' of 'bytearray' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:435(_mk_bitmap)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:485(_get_literal_prefix)
        2    0.000    0.000    0.000    0.000 {built-in method _signal.pthread_sigmask}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:187(disable_on_exception)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:392(Traversable)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:159(_path_isdir)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/posixpath.py:334(normpath)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:438(status_printer)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:282(_args_from_interpreter_flags)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:266(_supports_unicode)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1031(get_filename)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:171(register_after_fork)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:793(date)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:71(BaseProcess)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:30(BaseContext)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:81(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:407(_Pickler)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:214(socket)
       45    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/_distutils_hack/__init__.py:89(<lambda>)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:268(getuntil)
        5    0.000    0.000    0.000    0.000 {built-in method _sre.compile}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:105(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:1162(daemon)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/numbers.py:147(Real)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:584(_can_use)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_collections_abc.py:925(clear)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/bz2.py:27(BZ2File)
       85    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_compat_pickle.py:167(<genexpr>)
       21    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:244(<genexpr>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/numbers.py:294(Integral)
       32    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:163(colour)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/typing.py:1007(__init_subclass__)
       38    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:841(create_module)
        6    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:49(decorator)
       44    0.000    0.000    0.000    0.000 {method 'isidentifier' of 'str' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:76(TqdmDefaultWriteLock)
       70    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:16(<lambda>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1245(time)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:928(fix_flags)
       12    0.000    0.000    0.000    0.000 {built-in method builtins.round}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:156(__init__)
       13    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:81(_combine_flags)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:1335(_fixupParents)
       10    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:619(isstring)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:165(__setitem__)
       71    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:21(<lambda>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:473(timedelta)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:1404(__init__)
       51    0.000    0.000    0.000    0.000 {method 'lower' of 'str' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:494(unwrap)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:101(Random)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:152(wrapper_setattr)
       43    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_compat_pickle.py:165(<genexpr>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:252(_is_utf)
       13    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/collections/__init__.py:419(<genexpr>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:643(SpooledTemporaryFile)
       37    0.000    0.000    0.000    0.000 {method 'items' of 'mappingproxy' objects}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:37(__init__)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:76(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:437(<listcomp>)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:516(_get_charset_prefix)
       19    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:169(__setitem__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:81(BaseSelector)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:456(_generate_overlap_table)
        6    0.000    0.000    0.000    0.000 {built-in method fromkeys}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:368(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:259(getwhile)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:496(popitem)
       10    0.000    0.000    0.000    0.000 {method 'setter' of 'property' objects}
        1    0.000    0.000    0.000    0.000 {built-in method posix.sysconf}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/lzma.py:38(LZMAFile)
       16    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1481(<genexpr>)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:21(__enter__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:184(RLock)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:200(InspectLoader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:125(__eq__)
        7    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:443(__members__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/posixpath.py:60(isabs)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:67(TRLock)
        3    0.000    0.000    0.000    0.000 {built-in method posix.close}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:220(Process)
       21    0.000    0.000    0.000    0.000 {method 'pop' of 'set' objects}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_parse.py:296(_class_escape)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:354(__init__)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:226(__init__)
       13    0.000    0.000    0.000    0.000 {built-in method sys.intern}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/reduction.py:251(AbstractReducer)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:360(Barrier)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:241(_requires_builtin_wrapper)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:290(update)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:139(__getattr__)
       28    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2548(name)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1157(__hash__)
        1    0.000    0.000    0.000    0.000 {built-in method math.sqrt}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:346(ResourceReader)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:65(wraps)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:210(Condition)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/os.py:804(fsencode)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:661(SocketIO)
       10    0.000    0.000    0.000    0.000 {method 'getrandbits' of '_random.Random' objects}
        7    0.000    0.000    0.000    0.000 {built-in method builtins.vars}
       13    0.000    0.000    0.000    0.000 {method '__contains__' of 'frozenset' objects}
        8    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/sre_compile.py:477(_get_iscased)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:840(_is_valid_dispatch_type)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/_tqdm_pandas.py:1(<module>)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:2236(_create)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:218(_acquireLock)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1153(_comparable)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:217(__init_subclass__)
        3    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects}
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:222(__eq__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_compression.py:33(DecompressReader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:108(CalledProcessError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:46(SemLock)
        4    0.000    0.000    0.000    0.000 {built-in method builtins.id}
        1    0.000    0.000    0.000    0.000 {method 'fileno' of '_io.TextIOWrapper' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/numbers.py:267(Rational)
        8    0.000    0.000    0.000    0.000 {method 'bit_length' of 'int' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:786(TemporaryDirectory)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_collections_abc.py:779(items)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:50(_days_in_month)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/reduction.py:33(ForkingPickler)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:291(SelectSelector)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:342(_PollLikeSelector)
        7    0.000    0.000    0.000    0.000 {method 'mro' of 'type' objects}
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:45(_days_before_year)
        4    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:17(<genexpr>)
        3    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:16(<genexpr>)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/reduction.py:43(register)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:108(_platform_supports_abstract_sockets)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:757(_newname)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1214(IsoCalendarDate)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/resource_tracker.py:46(ResourceTracker)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/types.py:171(__get__)
        1    0.000    0.000    0.000    0.000 {built-in method math.exp}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:182(Finalize)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:88(PathEntryFinder)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:227(_releaseLock)
        2    0.000    0.000    0.000    0.000 {method 'pop' of 'list' objects}
        2    0.000    0.000    0.000    0.000 {built-in method math.log}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:200(_Framer)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/resource_tracker.py:48(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pkgutil.py:269(ImpLoader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/util.py:266(LazyLoader)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.sorted}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:348(__new__)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_weakrefset.py:17(__init__)
        1    0.000    0.000    0.000    0.000 {method 'close' of 'select.kqueue' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:128(_RandomNameSequence)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:459(TraversableResources)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:207(_BaseSelectorImpl)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:145(TimeoutExpired)
        7    0.000    0.000    0.000    0.000 {method 'setdefault' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:183(DisableOnWriteError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:226(DefaultContext)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:427(_TemporaryFileCloser)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:428(CompletedProcess)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:31(Finder)
        1    0.000    0.000    0.000    0.000 {method 'translate' of 'bytearray' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/typing.py:1350(runtime_checkable)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/gui.py:24(tqdm_gui)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:90(_make_methods)
        5    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:445(_check_tzinfo_arg)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:434(PollSelector)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:507(KqueueSelector)
        2    0.000    0.000    0.000    0.000 {method 'popitem' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:650(_use_posix_spawn)
        1    0.000    0.000    0.000    0.000 {built-in method posix.register_at_fork}
        2    0.000    0.000    0.000    0.000 {built-in method _weakref.proxy}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/functools.py:478(lru_cache)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:159(isfunction)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:117(Comparable)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:203(reducer)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:358(_ParentProcess)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/selectors.py:61(_SelectorMapping)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/_monitor.py:15(TMonitor)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/typing.py:1197(<genexpr>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:263(_Unframer)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/random.py:778(SystemRandom)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/datetime.py:1145(tzinfo)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:163(SimpleTextIOWrapper)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:229(__init__)
        6    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/signal.py:48(_wraps)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_compression.py:9(BaseStream)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:184(ResourceLoader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/weakref.py:353(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1147(__del__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:102(FormatReplace)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:253(ExecutionLoader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:1224(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:82(RLock)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:138(ObjectWrapper)
        1    0.000    0.000    0.000    0.000 {method 'difference' of 'set' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/posixpath.py:41(_get_sep)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:514(_is_wrapper)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:98(<listcomp>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:321(Event)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/tempfile.py:470(_TemporaryFileWrapper)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/runpy.py:25(_TempModule)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pkgutil.py:195(ImpImporter)
        3    0.000    0.000    0.000    0.000 {built-in method sys._getframe}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:771(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/logging/__init__.py:193(_checkLevel)
        2    0.000    0.000    0.000    0.000 {built-in method posix.getpid}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/numbers.py:12(Number)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:272(ForkProcess)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:293(ForkContext)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:368(ForkAwareThreadLock)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:299(SourceLoader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:214(EMA)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:233(get_context)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:51(MetaPathFinder)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/_collections_abc.py:802(__init__)
        1    0.000    0.000    0.000    0.000 /Users/wenyan/projects2024/efficient_python/test_queue.py:147(__init__)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:226(CallbackIOWrapper)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:282(_screen_shape_wrapper)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:197(get_start_method)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:279(SpawnProcess)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:286(ForkServerProcess)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:301(ForkServerContext)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:391(_MainProcess)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:123(Semaphore)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/runpy.py:48(_ModifiedArgv0)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/util.py:219(_LazyModule)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:137(Loader)
        3    0.000    0.000    0.000    0.000 {built-in method builtins.globals}
        2    0.000    0.000    0.000    0.000 {method 'replace' of 'str' objects}
        2    0.000    0.000    0.000    0.000 {built-in method builtins.callable}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:40(TqdmWarning)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:142(BoundedSemaphore)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/synchronize.py:159(Lock)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:272(_optim_args_from_interpreter_flags)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:343(AuthenticationString)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/reduction.py:211(_C)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:385(ForkAwareLocal)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/subprocess.py:105(SubprocessError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/_monitor.py:9(TqdmSynchronisationWarning)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/utils.py:79(<dictcomp>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/_dist_ver.py:1(<module>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:14(ProcessError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/socket.py:211(_GiveupOnSendfile)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/spawn.py:45(get_executable)
        2    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:536(is_set)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/threading.py:1147(daemon)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:97(_Stop)
        2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:782(is_package)
        1    0.000    0.000    0.000    0.000 {method 'insert' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {built-in method sys.getrecursionlimit}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/enum.py:792(value)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:20(TimeoutError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:23(AuthenticationError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:297(SpawnContext)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:73(PickleError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:77(PicklingError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/pickle.py:84(UnpicklingError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:69(Error)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:72(SameFileError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:79(ExecError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/util.py:48(debug)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/runpy.py:165(_Error)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/importlib/abc.py:290(FileLoader)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/inspect.py:2865(parameters)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:36(TqdmKeyError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:52(TqdmExperimentalWarning)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/context.py:17(BufferTooShort)
        1    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.RLock' objects}
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:32(TqdmTypeError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:57(TqdmDeprecationWarning)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:62(TqdmMonitorWarning)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/site-packages/tqdm/std.py:1301(<lambda>)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/multiprocessing/process.py:37(current_process)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:75(SpecialFileError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:82(ReadError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:85(RegistryError)
        1    0.000    0.000    0.000    0.000 /opt/anaconda3/envs/calc_photo/lib/python3.9/shutil.py:89(_GiveupOnFastCopy)
        1    0.000    0.000    0.000    0.000 {method '__init_subclass__' of 'object' objects}

我们把多线程和单线程的profile文件对比来看一下。

python并发与并行(六) ———— 正确的重构代码,以便用Queue做并发_多线程

从提供的两个 cProfile 性能分析报告来看,第一个报告是多线程版本的程序分析结果,而第二个报告是单线程版本的程序分析结果。下面是两者的对比和性能瓶颈原因分析:

多线程版本性能分析报告(threaded_prof):

  1. 总函数调用次数:18,014,274次。
  2. 总运行时间:3.377秒。
  3. 主要瓶颈
  • queue.put:450,100次调用,累积耗时1.163秒。
  • 线程锁操作(__enter____exit__):1,350,400次调用,累积耗时0.723秒和0.165秒。

单线程版本性能分析报告(threaded_prof_single_thread):

  1. 总函数调用次数:5,871,267次。
  2. 总运行时间:1.004秒。
  3. 主要瓶颈
  • conway_game.py:step_cell:450,000次调用,累积耗时0.907秒。
  • conway_game.py:count_neighbors:450,000次调用,累积耗时0.648秒。

性能瓶颈原因分析:

  1. 多线程开销
  • 多线程版本中,大量的时间花费在了队列的 putget 操作以及线程锁的管理上。这表明线程间的同步和通信可能是性能瓶颈。
  1. 锁竞争
  • 多线程程序中,线程锁的获取和释放操作非常频繁,这可能导致线程竞争,从而影响性能。
  1. I/O操作
  • 在单线程版本中,print 函数的调用(splitlines)占用了一定的时间,而在多线程版本中,I/O操作的影响相对较小。
  1. 算法效率
  • 单线程版本的主要时间花费在 step_cellcount_neighbors 函数上,这表明算法本身的效率可能是性能瓶颈。
  1. CPU核心利用率
  • 单线程版本受限于单个CPU核心的处理能力,而多线程版本可能由于线程切换和同步开销,并没有实现预期的加速比。
  1. 内存使用
  • 多线程版本可能需要更多的内存来存储线程栈和共享数据结构,这可能影响缓存效率和内存带宽。
  1. 程序结构
  • 多线程版本的程序结构可能更复杂,增加了调试和优化的难度。

结论:

从两个报告的对比来看,多线程版本并没有实现预期的性能提升,主要瓶颈在于线程间的同步和通信开销。


标签:opt,python,photo,py,Queue,并发,python3.9,calc,0.000
From: https://blog.51cto.com/u_15302822/11882943

相关文章

  • 基于Python的人脸识别考勤管理系统-计算机毕业设计源码+LW文档
    摘要随着信息技术的迅猛发展,面部识别技术已逐渐成为身份验证领域的研究热点。基于Python的人脸识别考勤管理系统,作为一种新兴的身份验证方式,具有重要的研究意义和应用价值。该系统通过捕捉和分析人脸特征,实现快速、准确的身份验证,解决了传统考勤方式中可能存在的冒用、伪造等问题......
  • 【Python技术学习】- python基础语法
    编码默认情况下,Python3源码文件以 UTF-8 编码,所有字符串都是unicode字符串。当然你也可以为源码文件指定不同的编码:#-*-coding:cp-1252-*-上述定义允许在源文件中使用Windows-1252字符集中的字符编码,对应适合语言为保加利亚语、白罗斯语、马其顿语、俄语、塞......
  • Python比C语言到底有什么优势?为什么越来越多人都学python?
    Python作为一种高级编程语言,在众多编程语言中脱颖而出,主要得益于其多方面的优势。以下是Python相比于其他语言的一些显著优势:简单易学:Python的语法清晰、简洁,易于阅读和编写,这使得它成为初学者的首选语言。其语法结构接近于自然语言,减少了学习曲线的陡峭度。丰富的库和框......
  • 顶级的python入门教程!小白到大师,从这篇教程开始!
    1.为什么要学习Python?学习Python的原因有很多,以下是几个主要的原因:广泛应用:Python被广泛应用于Web开发、数据科学、人工智能、机器学习、自动化运维、网络爬虫、科学计算、游戏开发等多个领域。掌握Python意味着你可以在这些领域中找到丰富的职业机会。入门简单:Python的......
  • 在新项目中创建 Python 虚拟环境
    在新项目中创建Python虚拟环境可以帮助您管理项目的依赖项,避免与其他项目的冲突。以下是创建Python虚拟环境的步骤:1.安装Python确保您已经安装了Python。您可以在终端或命令提示符中运行以下命令来检查是否已安装:python--version或者python3--version如果......
  • Python自动化测试面试题总结_pytest框架面试题
    ???16、请用python脚本实现从1到100的求和。???17、编写一个匿名函数,使其能够进行加法运算,例如说输入1,2能计算结果为3???18、list_1=[1,2,1,2,15,4,3,2,1,2],去除list_1的重复值,并且从大到小排序。???19、统计字符串中的单词个数,这里的单词指的是连续的不是空格的......
  • Debian修改默认Python
    Debian修改默认Python     Linuxversion4.9.0-4-686-pae这是linux系统版本,我这边使用的是debian9.2还是9.0来着,应该都是通用的。    系统中默认安装了多个版本的python,其中默认使用的是python2.7,现在我所学习的是python3的命令,为了便于使用,需要把python3设置为默......
  • 高并发系统-使用自定义日志埋点快速排查问题
    背景在高并发的系统中,通常不会打印除参数校验失败或捕获异常之外的日志,防止对接口的性能产生影响。那对于请求不符合预期的情况,我们如何快速找到是哪块逻辑影响的至关重要。Pfinder提供的链路监控,更多的是性能层面的监控,无法满足我们上述的诉求。下面我将通过自定义通用上下文,添加......
  • 使用Python的Matplotlib和Seaborn库进行数据可视化的全面指南
    数据可视化是数据科学和分析中不可或缺的一部分,而Python中的Matplotlib和Seaborn库为用户提供了强大的工具来创建各种可视化图表。本文将介绍如何使用这两个库进行数据可视化,并提供一些实用的代码示例和解析。安装Matplotlib和Seaborn首先,确保你已经安装了Matplotlib和Seaborn库。......
  • python-春游
    [题目描述]老师带领同学们春游。已知班上有 N 位同学,每位同学有从 0 到 N−1 的唯一编号。到了集合时间,老师确认是否所有同学都到达了集合地点,就让同学们报出自己的编号。到达的同学都会报出自己的编号,不会报出别人的编号,但有的同学很顽皮,会多次报出。你能帮老师找出有......