【多进程并发笔记】Python-Multiprocess

调用函数后,函数内的变量如何释放?

在 Python 中,函数内部的局部变量在函数执行完毕后会被释放.这是因为函数内的局部变量只在函数执行期间存在,当函数执行完毕后,这些局部变量所占用的内存空间会被自动释放.

def my_function():
    # 在函数内部定义一个局部变量
    message = "Hello, World!"
    print(message)

# 调用函数
my_function()

# 函数执行完毕后,局部变量 message 被释放

在这个例子中,当函数 my_function 执行完毕后,局部变量 message 被释放,不再占用内存空间.

需要注意的是:函数内部的变量释放并不意味着函数返回值所占用的内存会被释放.

如果函数返回了一个引用类型的对象(如列表、字典等),这个对象在函数执行完毕后仍然可以被外部代码所引用,直到没有任何引用指向它时,Python 的垃圾回收机制才会将其释放.

总之,函数内的局部变量会在函数执行完毕后被释放,但返回值所占用的内存空间的释放取决于对象是否还被引用.

python2.7怎么使用多线程加速for loop

在 Python 2.7 中,你可以使用 threading 模块来实现多线程加速 for 循环.在 Python 2.7 中,threading 是用来创建和管理线程的内置模块.在 for 循环中使用多线程可以加速处理大量数据或者 IO 密集型任务.

以下是一个简单的示例,演示了如何在 Python 2.7 中使用多线程来加速 for 循环:

import threading

# 定义一个函数,用于并发执行的任务
def process_data(data):
    # 这里可以放入需要处理的任务
    print("Processing data:", data)

# 假设有一个包含需要处理数据的列表
data_list = [1, 2, 3, 4, 5]

# 创建线程列表
threads = []

# 创建并启动线程
for data in data_list:
    # 创建线程,并将函数和数据作为参数传递给线程的构造函数
    t = threading.Thread(target=process_data, args=(data,))
    threads.append(t)
    t.start()

# 等待所有线程执行完毕
for t in threads:
    t.join()

print("All threads have finished processing")

在这个示例中,我们首先定义了一个处理数据的函数 process_data,然后创建了一个包含需要处理的数据的列表 data_list.接着,我们创建了多个线程,并将函数和数据作为参数传递给线程的构造函数 threading.Thread,然后启动这些线程并等待它们执行完毕.

需要注意的是,在 Python 2.7 中,由于全局解释器锁 (GIL) 的存在,多线程并不能有效地利用多核 CPU.如果想要充分利用多核 CPU,可以考虑使用 multiprocessing 模块来实现多进程加速.

总之,在 Python 2.7 中,你可以使用 threading 模块来在 for 循环中实现多线程加速,但要注意 GIL 对多线程并发执行的影响.

多进程进程池,函数序列化错误的处理

报错:

RuntimeError  File "C:\Python27\lib\multiprocessing\forking.py", line 258, in __init__
is not going to be frozen to produce a Windows executable.''')
            Attempt to start a new process before the current process
            has finished its bootstrapping phase.

            This probably means that you are on Windows and you have
            forgotten to use the proper idiom in the main module:

                if __name__ == '__main__':

这个错误是由于在使用 multiprocessing 模块时,Python 2.7 试图对函数进行序列化 (pickling) 以便在多个进程之间传递.然而,由于某些函数不是可以被序列化的(可被pickling),因此会导致报错.

为了解决这个问题,可以将需要并发执行的函数放在一个单独的文件中,然后使用 if __name__ == '__main__': 来保护多进程的主入口点,这样可以避免 Windows 下的报错.下面是一个修改后的示例:

# 在新的文件中定义需要并行执行的函数
# 例如,放在一个名为 parallel.py 的文件中
from multiprocessing import Pool

# 定义需要并行执行的任务
def process_data(data):
    # 这里可以放入需要处理的任务
    print("Processing data:", data)

# 添加保护主入口点的代码
if __name__ == "__main__":
    # 创建进程池
    with Pool() as pool:
        # 假设有一个包含需要处理数据的列表
        data_list = [1, 2, 3, 4, 5]

        # 并行执行任务
        pool.map(process_data, data_list)

然后在你的主程序中调用这个新的文件:

from multiprocessing import Pool
from parallel import process_data

if __name__ == "__main__":
    with Pool() as pool:
        data_list = [1, 2, 3, 4, 5]
        pool.map(process_data, data_list)

将并发执行的函数放在一个单独的文件中,并使用 if __name__ == '__main__': 来保护主入口点,可以解决在 Windows 下使用 multiprocessing 模块时的序列化错误.

Time模块计算程序运行时间

在 Python 中,你可以使用 time 模块来计算程序的运行时间.下面我将向你展示如何使用该模块来测量代码块的执行时间.

import time

# 记录开始时间
start_time = time.time()

# 在这里放置你想要测量执行时间的代码块
# 例如,一个耗时的计算任务或者一个函数的执行

# 记录结束时间
end_time = time.time()

# 计算时间差
execution_time = end_time - start_time
print("程序执行时间为:", execution_time, "秒")

在这个示例中,用 time.time() 记录了代码块开始和结束的时间戳,然后计算它们之间的差值,从而得到代码块的执行时间.

使用多进程,Start()后,如何获得返回值?

在 Python 中,进程池是可以直接得到返回值的,但使用多进程创建一个进程后,通常情况下无法直接获得函数的返回值,因为子进程和父进程是相互独立的.然而,你可以通过一些手段来获取子进程的返回值.

一种常用的方法是使用进程间通信(Inter-process Communication, IPC).在 Python 中,可以使用 multiprocessing 模块提供的队列(Queue)和管道(Pipe)来实现进程间通信,从而传递子进程的返回值给父进程.下面是一个示例:

import multiprocessing

# 定义一个函数,用于在子进程中执行
def process_func(queue):
    result = 42  # 这里可以是任何需要返回的值
    queue.put(result)  # 将结果放入队列中

if __name__ == "__main__":
    # 创建一个队列用于进程间通信
    queue = multiprocessing.Queue()

    # 创建子进程并启动
    process = multiprocessing.Process(target=process_func, args=(queue,))
    process.start()

    # 等待子进程执行完毕
    process.join()

    # 获取子进程返回的结果
    result = queue.get()

    print("子进程返回值:", result)

在这个示例中,我们在子进程中执行 process_func 函数,并将结果放入队列中.在父进程中,我们可以通过调用队列的 get 方法来获取子进程的返回值.

使用多进程并行,每个进程都将结果写入sqlite3数据库,可以么

可以使用多进程并行处理,在每个进程中将结果写入到 SQLite3 数据库.但需要注意的是,SQLite3 在写入时可能会有一些限制,因此在多进程环境下需要格外小心.

下面是一个简单的示例,演示了如何在多进程中将结果写入 SQLite3 数据库:

import sqlite3
import multiprocessing

# 定义一个函数,用于在子进程中执行
def write_to_database(process_id, result):
    # 连接数据库
    conn = sqlite3.connect('results.db')
    c = conn.cursor()

    # 执行写入操作
    c.execute("INSERT INTO results VALUES (?, ?)", (process_id, result))

    # 提交更改并关闭连接
    conn.commit()
    conn.close()

if __name__ == "__main__":
    # 创建一个 SQLite3 数据库
    conn = sqlite3.connect('results.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS results
                 (process_id INTEGER, result TEXT)''')
    conn.commit()
    conn.close()

    # 创建多个进程并启动
    processes = []
    for i in range(5):
        process = multiprocessing.Process(target=write_to_database, args=(i, f"Result {i}"))
        processes.append(process)
        process.start()

    # 等待所有子进程执行完毕
    for process in processes:
        process.join()

    print("所有进程已经执行完毕,结果已写入数据库")

在这个示例中,我们首先创建了一个 SQLite3 数据库,然后定义了一个函数 write_to_database,用于在每个子进程中执行数据库写入操作.在主程序中,我们创建了多个进程,每个进程将结果写入数据库.

需要注意的是,SQLite3 在多线程/多进程下有一些限制,具体表现取决于使用的 SQLite3 驱动程序.通常建议在多进程环境中谨慎地使用 SQLite3,并注意处理可能出现的并发访问问题.如果需要在多进程或多线程环境下执行大量数据库操作,考虑使用其他支持并发访问的数据库,如 PostgreSQL 或 MySQL.

python创建进程池

在 Python 中,你可以使用 multiprocessing 模块来创建进程池.进程池可以帮助你管理多个子进程,从而可以并发执行多个任务.

下面是一个简单的示例,演示了如何在 Python 中创建进程池:

import multiprocessing

# 定义一个函数,用于在子进程中执行
def process_func(data):
    result = data * 2  # 这里可以是任何需要处理的任务
    return result

if __name__ == "__main__":
    # 创建一个进程池,指定最大进程数为 4
    with multiprocessing.Pool(processes=4) as pool:
        # 定义一个需要处理的数据列表
        data_list = [1, 2, 3, 4, 5]

        # 并行执行任务,并获取结果
        results = pool.map(process_func, data_list)

        # 打印结果
        print("处理结果:", results)

在这个示例中,我们首先创建了一个进程池,指定最大进程数为 4.然后,我们定义了一个需要处理的数据列表 data_list,并使用 pool.map 方法并行执行了这些数据的处理,最后获取并打印了执行的结果.

通过使用进程池,你可以很方便地并发执行多个子任务,从而提高程序的执行效率.需要注意的是,进程池并不适用于所有类型的任务,比如对于 IO 密集型任务,有时候使用线程池可能会更加合适.

进程池的最大进程数怎么确定

确定进程池中进程的最大数量取决于多个因素,包括系统资源、任务类型和性能需求.

  1. CPU 核心数量:通常来说,进程池的最大进程数不应该超过CPU核心的数量.因为如果进程数超过了 CPU 核心数量,就会导致进程上下文切换频繁,从而降低整体性能.

  2. 任务类型:如果你的任务是 CPU 密集型的,即任务需要大量的 CPU 计算资源,那么通常可以根据 CPU 核心数量来确定最大进程数.如果任务是 IO 密集型的,即任务需要大量的 IO 操作,可以允许更多的进程,因为 IO 操作通常会释放 CPU 的执行时间,允许更多的进程并发执行.

  3. 内存和其他资源:每个进程都会消耗系统资源,包括内存、文件描述符等.因此,你需要考虑系统的可用资源来确定最大进程数.如果系统资源不足,进程数过多会导致系统性能下降甚至崩溃.

  4. 性能需求:有时候,为了提高任务执行速度,可以略微增加进程池的最大进程数.在实际应用中,通常需要进行一些基准测试和性能优化,以确定最佳的进程池大小.

一般来说,初始时可以选择一个合理的进程池大小,进行性能测试和观察系统资源使用情况,根据实际情况逐步调整进程池大小,以取得最佳性能.

py2.7字典合并的办法

在 Python 2.7 中,你可以使用 update 方法来合并两个字典.这个方法将一个字典的内容更新到另一个字典中,如果存在相同的键,则以被更新字典中的值为准.

以下是一个示例,演示了如何在 Python 2.7 中合并两个字典:

# 定义两个字典
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

# 使用 update 方法合并字典
dict1.update(dict2)

print(dict1)

在这个示例中,dict1.update(dict2) 将字典 dict2 中的内容更新到了 dict1 中,最终得到了合并后的字典.此时,如果存在相同的键(例如 'b'),则以被更新字典中的值为准,因此最终的结果是 {'a': 1, 'b': 3, 'c': 4}.

除了 update 方法,你还可以使用字典解析和 ** 操作符来实现字典的合并.以下是另外一种合并字典的方法:

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

# 使用字典解析和 ** 操作符合并字典
merged_dict = {key: value for d in [dict1, dict2] for key, value in d.items()}

print(merged_dict)

无论使用哪种方法,这些技巧都可以帮助你在 Python 2.7 中实现字典的合并操作.

多进程的join()方法

在多进程中,当主进程等待子进程执行完毕时,可以使用 join() 方法来实现.


import multiprocessing

def create_items(pipe):
    send_c, recv_c = pipe
    import numpy as np
    import time
    # 函数计算得到一个数据结果
    data=np.random.rand(20,20)
    print("start time:{}, process name:{}".format(time.time(),multiprocessing.current_process().name))
    # send_c.send(data)
    time.sleep(0.5)
if __name__== '__main__':
    
    pipe_1 = multiprocessing.Pipe(True)
    ps=[]
    for i in range(20):
        p = multiprocessing.Process(target=create_items,name="Process-{}".format(i), args=(pipe_1,))
        ps.append(p)
        
    for p in ps:
        p.start()
        # print("Process-{} start,alive={}".format(p.name,p.is_alive()))
        # p.join()
        # print("Process-{} jion,alive={}".format(p.name,p.is_alive()))
        
    import time
    time.sleep(2)
    
    # _,recv_c = pipe_1
    # getdata=[]
    # for i in range(21):
    #     data = recv_c.recv()
    #     print(data.shape)
    #     getdata.append(data)
    # # print(data)
    for p in ps:
        print("Process-{} ,alive={}".format(p.name,p.is_alive()))
        p.terminate()
        print("Process-{} terminate,alive={}".format(p.name,p.is_alive()))

输出:

start time:1715848697.91, process name:Process-1
start time:1715848697.92, process name:Process-3
start time:1715848697.93, process name:Process-9
start time:1715848697.93, process name:Process-2
start time:1715848697.94, process name:Process-5
start time:1715848697.94, process name:Process-0
start time:1715848697.94, process name:Process-4
start time:1715848697.94, process name:Process-10
start time:1715848697.95, process name:Process-7
start time:1715848698.16, process name:Process-12
start time:1715848698.17, process name:Process-16
start time:1715848698.17, process name:Process-6
start time:1715848698.17, process name:Process-13
start time:1715848698.17, process name:Process-11
start time:1715848698.18, process name:Process-17
start time:1715848698.18, process name:Process-14
start time:1715848698.22, process name:Process-8
ssstart time:1715848698.22, process name:Process-18tart time:1715848698.22, process name:Process-15tart time:1715848698.22, process name:Process-19


Process-Process-0 ,alive=False
Process-Process-0 terminate,alive=False
Process-Process-1 ,alive=False
Process-Process-1 terminate,alive=False
Process-Process-2 ,alive=False
Process-Process-2 terminate,alive=False
Process-Process-3 ,alive=False
Process-Process-3 terminate,alive=False
Process-Process-4 ,alive=False
Process-Process-4 terminate,alive=False
Process-Process-5 ,alive=False
Process-Process-5 terminate,alive=False
Process-Process-6 ,alive=False
Process-Process-6 terminate,alive=False
Process-Process-7 ,alive=False
Process-Process-7 terminate,alive=False
Process-Process-8 ,alive=False
Process-Process-8 terminate,alive=False
Process-Process-9 ,alive=False
Process-Process-9 terminate,alive=False
Process-Process-10 ,alive=False
Process-Process-10 terminate,alive=False
Process-Process-11 ,alive=False
Process-Process-11 terminate,alive=False
Process-Process-12 ,alive=False
Process-Process-12 terminate,alive=False
Process-Process-13 ,alive=False
Process-Process-13 terminate,alive=False
Process-Process-14 ,alive=False
Process-Process-14 terminate,alive=False
Process-Process-15 ,alive=False
Process-Process-15 terminate,alive=False
Process-Process-16 ,alive=False
Process-Process-16 terminate,alive=False
Process-Process-17 ,alive=False
Process-Process-17 terminate,alive=False
Process-Process-18 ,alive=False
Process-Process-18 terminate,alive=False
Process-Process-19 ,alive=False
Process-Process-19 terminate,alive=False

在start()进程后,不加join()方法,那么每个进程开始启动计算的时间几乎一致.加入join()方法后,一个进程会等计算完成后才开始下一个进程.

# -*- coding: utf-8 -*-
import multiprocessing
from test import square,foo
def create_items(pipe):
    send_c, recv_c = pipe
    import numpy as np
    import time
    # 函数计算得到一个数据结果
    data=np.random.rand(20,20)
    print("start time:{}, process name:{}".format(time.time(),multiprocessing.current_process().name))
    # send_c.send(data)
    time.sleep(0.5)

if __name__== '__main__':
    
    pipe_1 = multiprocessing.Pipe(True)
    ps=[]
    for i in range(20):
        p = multiprocessing.Process(target=create_items,name="Process-{}".format(i), args=(pipe_1,))
        ps.append(p)
        
    for p in ps:
        p.start()
        print("Process-{} start,alive={}".format(p.name,p.is_alive()))
        p.join()
    import time
    time.sleep(2)
    print(ps[0].is_alive())
    for p in ps:
        print("Process-{} ,alive={}".format(p.name,p.is_alive()))
        time.sleep(0.5)
        p.terminate()
        print("Process-{} terminate,alive={}".format(p.name,p.is_alive()))

输出:

Process-Process-0 start,alive=True
start time:1715849085.02, process name:Process-0
Process-Process-1 start,alive=True
start time:1715849085.59, process name:Process-1
Process-Process-2 start,alive=True
start time:1715849086.18, process name:Process-2
Process-Process-3 start,alive=True
start time:1715849086.76, process name:Process-3
Process-Process-4 start,alive=True
start time:1715849087.34, process name:Process-4
Process-Process-5 start,alive=True
start time:1715849087.92, process name:Process-5
Process-Process-6 start,alive=True
start time:1715849088.51, process name:Process-6
Process-Process-7 start,alive=True
start time:1715849089.1, process name:Process-7
Process-Process-8 start,alive=True
start time:1715849089.67, process name:Process-8
Process-Process-9 start,alive=True
start time:1715849090.26, process name:Process-9
Process-Process-10 start,alive=True
start time:1715849090.84, process name:Process-10
Process-Process-11 start,alive=True
start time:1715849091.41, process name:Process-11
Process-Process-12 start,alive=True
start time:1715849092.0, process name:Process-12
Process-Process-13 start,alive=True
start time:1715849092.58, process name:Process-13
Process-Process-14 start,alive=True
start time:1715849093.16, process name:Process-14
Process-Process-15 start,alive=True
start time:1715849093.74, process name:Process-15
Process-Process-16 start,alive=True
start time:1715849094.32, process name:Process-16
Process-Process-17 start,alive=True
start time:1715849094.9, process name:Process-17
Process-Process-18 start,alive=True
start time:1715849095.49, process name:Process-18
Process-Process-19 start,alive=True
start time:1715849096.08, process name:Process-19
False
Process-Process-0 ,alive=False
Process-Process-0 terminate,alive=False
Process-Process-1 ,alive=False
Process-Process-1 terminate,alive=False
Process-Process-2 ,alive=False
Process-Process-2 terminate,alive=False
Process-Process-3 ,alive=False
Process-Process-3 terminate,alive=False
Process-Process-4 ,alive=False
Process-Process-4 terminate,alive=False
Process-Process-5 ,alive=False
Process-Process-5 terminate,alive=False
Process-Process-6 ,alive=False
Process-Process-6 terminate,alive=False
Process-Process-7 ,alive=False
Process-Process-7 terminate,alive=False
Process-Process-8 ,alive=False
Process-Process-8 terminate,alive=False
Process-Process-9 ,alive=False
Process-Process-9 terminate,alive=False
Process-Process-10 ,alive=False
Process-Process-10 terminate,alive=False
Process-Process-11 ,alive=False
Process-Process-11 terminate,alive=False
Process-Process-12 ,alive=False
Process-Process-12 terminate,alive=False
Process-Process-13 ,alive=False
Process-Process-13 terminate,alive=False
Process-Process-14 ,alive=False
Process-Process-14 terminate,alive=False
Process-Process-15 ,alive=False
Process-Process-15 terminate,alive=False
Process-Process-16 ,alive=False
Process-Process-16 terminate,alive=False
Process-Process-17 ,alive=False
Process-Process-17 terminate,alive=False
Process-Process-18 ,alive=False
Process-Process-18 terminate,alive=False
Process-Process-19 ,alive=False
Process-Process-19 terminate,alive=False
posted @ 2024-06-01 11:21  FE-有限元鹰  阅读(41)  评论(0编辑  收藏  举报