python使用multiprocessing,函数没有运行

为了加快运行速度使用了multiprocessing,但是函数都没有运行,不知道问题出在哪,共有7个函数需要多进程运行,后面5个与前面两个基本类似,都是在for hour in hours下运行,大致的代码如下

def map()
  .....

def wind_shear(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time):
    ...
    
def draw_w(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time):
    ...

def ...
    
def f1():
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)              
    
def f2():
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        draw_w(ds, lon_range, lat_range, lons, lats, time, ds_time)     
    
def f3():
...

if __name__ == '__main__':
    map()
    for i in j:
        ...
        ...
        time = ...
        hours = ...
        ds1 = ...
        ds = ...
        lon = ...
        lat = ...   
        lon_range = ....
        lat_range = ....
        lons,lats = ....
        lon_2d, lat_2d = ....
        lon_2d[lon_2d > 180] = ....
        p1 =  multiprocessing.Process(target= f1)
        p2 =  multiprocessing.Process(target= f2)
        p3 =  multiprocessing.Process(target= f3)
        .....
        p1.start()
        p2.start()
        p3.start()
        .....

该回答引用ChatGPT

可能是因为在运行多进程时,函数中使用的变量没有被正确传递,导致函数无法正常执行。由于变量的作用域问题,函数中的变量默认为局部变量,需要通过参数传递或声明为全局变量。

您可以将需要传递给函数的变量作为参数传递给函数,或者将其声明为全局变量。比如:

1、将变量作为参数传递给函数:


def f1(ds, lon_range, lat_range, lons, lats, time, year, month, day, hours):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)

if __name__ == '__main__':
    ...
    p1 =  multiprocessing.Process(target=f1, args=(ds, lon_range, lat_range, lons, lats, time, year, month, day, hours))
    ...
    p1.start()

2、将变量声明为全局变量:

def f1():
    global ds, lon_range, lat_range, lons, lats, time, year, month, day, hours
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)

if __name__ == '__main__':
    global ds, lon_range, lat_range, lons, lats, time, year, month, day, hours
    ...
    ds = ...
    lon_range = ....
    lat_range = ....
    lons,lats = ....
    time = ...
    year = ...
    month = ...
    day = ...
    hours = ...
    ...
    p1 =  multiprocessing.Process(target=f1)
    ...
    p1.start()

请注意,如果您使用了全局变量,需要在每个进程中显式声明变量为全局变量,以便进程可以访问该变量。另外,由于进程之间是独立的,它们无法共享内存中的变量,因此您需要将变量传递给函数或将其声明为全局变量。

那hours到底是个什么呢,迭代器只能迭代一次

根据您提供的代码,我无法确定问题的根本原因。但是,如果您使用multiprocessing模块时函数没有运行,可能会有以下一些原因:

函数需要传入参数,但是在multiprocessing.Process()中没有传入参数,导致函数没有正确运行。在这种情况下,您可以使用args参数将所需参数传递给函数。

函数中使用的变量可能与其他进程共享,但这些变量未被正确保护。在这种情况下,您需要使用multiprocessing.Lock()等对象对共享变量进行保护。

进程可能在没有完全执行函数的情况下就被终止了。这可能是因为主进程(主程序)已经完成并退出,而子进程仍在运行。您可以使用join()方法,确保所有子进程在主进程退出之前已经完成。

检测一下 hours 是不是空的,或者其他类型, 在for前面加个打印, 应该是执行了的

参考GPT和自己的思路,在使用multiprocessing时,函数不能直接使用外部定义的变量和函数,需要将需要使用的变量和函数在主进程中进行定义和导入。因为子进程中不会自动导入主进程中的变量和函数,所以需要在主进程中将它们定义好,并将它们作为参数传递给子进程。

可以将需要在子进程中使用的变量和函数作为参数传递给对应的函数,然后在函数中使用这些参数。例如:

def f1(ds, lon_range, lat_range, lons, lats, time, hours, year, month, day):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time) 

def f2(ds, lon_range, lat_range, lons, lats, time, hours, year, month, day):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        draw_w(ds, lon_range, lat_range, lons, lats, time, ds_time) 

# 主进程中的变量和函数
if __name__ == '__main__':
    map()
    for i in j:
        ...
        ...
        time = ...
        hours = ...
        ds1 = ...
        ds = ...
        lon = ...
        lat = ...   
        lon_range = ....
        lat_range = ....
        lons,lats = ....
        lon_2d, lat_2d = ....
        lon_2d[lon_2d > 180] = ....

        # 创建子进程
        p1 =  multiprocessing.Process(target=f1, args=(ds, lon_range, lat_range, lons, lats, time, hours, year, month, day))
        p2 =  multiprocessing.Process(target=f2, args=(ds, lon_range, lat_range, lons, lats, time, hours, year, month, day))
        ...
        # 开始子进程
        p1.start()
        p2.start()
        ...  



在上述代码中,将需要在子进程中使用的变量和函数作为参数传递给对应的函数 f1 和 f2,并在主进程中创建子进程时使用 args 参数将这些参数传递给对应的函数。这样子进程就可以访问并使用这些变量和函数了。

参考GPT的回答内容,根据您提供的代码,可能是因为您在使用multiprocessing时没有将参数传递给子进程。在 multiprocessing 中,由于子进程无法直接访问父进程的变量,因此必须使用进程间通信来传递参数。建议使用 multiprocessing.Queue 来传递参数。

例如,在 f1() 中,您可以在循环中将参数放入队列中:

def f1(queue):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        queue.put((ds, lon_range, lat_range, lons, lats, time, ds_time))


在主程序中,您可以使用以下代码创建一个队列,并将其传递给子进程:

if __name__ == '__main__':
    map()
    for i in j:
        ...
        ...
        time = ...
        hours = ...
        ds1 = ...
        ds = ...
        lon = ...
        lat = ...   
        lon_range = ....
        lat_range = ....
        lons,lats = ....
        lon_2d, lat_2d = ....
        lon_2d[lon_2d > 180] = ....
        queue = multiprocessing.Queue()
        p1 = multiprocessing.Process(target=f1, args=(queue,))
        ...


然后,在 wind_shear() 中,您可以从队列中获取参数:

def wind_shear(queue):
    while True:
        ds, lon_range, lat_range, lons, lats, time, ds_time = queue.get()
        if ds is None:
            break
        ...


请注意,您需要在队列中放置一个 None 值以便通知子进程退出循环,以避免死锁的情况。

您可以按照相同的方式修改其他子进程函数,以便正确传递参数。

hours可能为none,建议debug一下

经过分析,问题出在函数中使用到了全局变量,而多进程中的进程间是没有共享全局变量的。因此,需要将这些全局变量作为参数传递给函数。修改后的代码如下:

def f1(ds, lon_range, lat_range, lon, lat, lons, lats, time, hours, year, month, day):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)

def f2(ds, lon_range, lat_range, lon, lat, lons, lats, time, hours, year, month, day):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        draw_w(ds, lon_range, lat_range, lons, lats, time, ds_time)

def f3(ds, lon_range, lat_range, lon, lat, lons, lats, time, hours, year, month, day):
    ...

if __name__ == '__main__':
    map()
    for i in j:
        ...
        ...
        time = ...
        hours = ...
        ds1 = ...
        ds = ...
        lon = ...
        lat = ...
        lon_range = ....
        lat_range = ....
        lons,lats = ....
        lon_2d, lat_2d = ....
        lon_2d[lon_2d > 180] = ....
        p1 =  multiprocessing.Process(target= f1, args=(ds, lon_range, lat_range, lon, lat, lons, lats, time, hours, year, month, day))
        p2 =  multiprocessing.Process(target= f2, args=(ds, lon_range, lat_range, lon, lat, lons, lats, time, hours, year, month, day))
        p3 =  multiprocessing.Process(target= f3, args=(ds, lon_range, lat_range, lon, lat, lons, lats, time, hours, year, month, day))
        .....
        p1.start()
        p2.start()
        p3.start()

在使用multiprocessing库时,如果函数中使用到了全局变量,那么这些变量需要作为参数传递给函数。否则,函数就不能正常运行。这是由于多进程中的进程间是没有共享全局变量的。因此,在编写多进程程序时,需要注意这一点,确保程序能够正常运行。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
您的代码中没有展示完整的map()函数,所以无法确定问题是否出现在该函数中。但是,我注意到您的f1()和f2()函数似乎没有传递任何参数给它们调用的wind_shear()和draw_w()函数。这可能是导致函数没有运行的原因。

由于您在if name == 'main'中创建了多个进程,每个进程都执行f1(),f2()等函数中的for hour in hours:循环。但是,在循环中,wind_shear()和draw_w()函数需要的参数(如ds,lon_range,lat_range等)似乎没有被传递给它们。

您可以考虑将这些参数传递给f1()和f2()函数,并使用args参数将它们传递给wind_shear()和draw_w()函数。例如:

def f1(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)              
    
def f2(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        draw_w(ds, lon_range, lat_range, lons, lats, time, ds_time)     
    
if __name__ == '__main__':
    map()
    for i in j:
        ...
        ...
        time = ...
        hours = ...
        ds1 = ...
        ds = ...
        lon = ...
        lat = ...   
        lon_range = ....
        lat_range = ....
        lons,lats = ....
        lon_2d, lat_2d = ....
        lon_2d[lon_2d > 180] = ....
        p1 =  multiprocessing.Process(target=f1, args=(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time))
        p2 =  multiprocessing.Process(target=f2, args=(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time))
        p1.start()
        p2.start()
        p1.join()
        p2.join()


这样,您可以确保wind_shear()和draw_w()函数可以访问到需要的参数。另外,我注意到您在创建进程之后并没有使用join()方法等待进程的完成,这可能也是导致问题的原因之一。我已经在代码中添加了join()方法。

“Devil组”引证GPT后的撰写:
可能出现问题的地方可能有以下几点:

  • 在定义函数f1、f2、f3等时,没有将参数传递给它们。因此,在函数中使用的变量(例如,ds,lon_range等)必须在函数外部定义为全局变量,否则函数可能无法正常工作。
  • 要使用multiprocessing.Queue等数据结构来传递数据和结果。多进程之间不能直接共享内存,因此不能直接共享变量。要将需要传递的数据放入Queue中,然后在子进程中从Queue中获取它们。
  • 要确保所有子进程在父进程结束前都被关闭。否则,可能会出现子进程一直运行的情况,从而导致程序无法正常退出。

1.在定义函数f1、f2等时,将参数传递给它们。例如:

def f1(ds, lon_range, lat_range, lons, lats, time, year, month, day):
    for hour in hours:
        ds_time = '%s'%(year)+'-'+'%s'%(month)+'-'+'%s'%(day)+'T'+'%s'%(hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)


2.在主程序中创建一个Queue,然后将需要传递的数据放入Queue中。例如:

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    map()
    for i in j:
        ...
        ...
        queue.put((ds, lon_range, lat_range, lons, lats, time, year, month, day, hours))
        ...


在函数f1、f2等中,使用queue.get()从Queue中获取需要的数据。

3.在主程序结束前,确保所有子进程都已经结束。例如:

if __name__ == '__main__':
    ...
    p1.start()
    p2.start()
    p3.start()
    ...
    p1.join()
    p2.join()
    p3.join()


在join()函数执行后,程序会等待所有子进程结束后再退出

可能是因为在多进程环境下,共享变量出现了问题。像ds, lon_range, lat_range, lons, lats等变量,如果在主程序中被定义和赋值,需要使用multiprocessing.Manager().list()或者multiprocessing.Manager().dict()来进行共享。另外,确保所有引用的模块都已导入。最好添加异常处理语句来捕获潜在的错误。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
多进程编程需要特别注意的问题:

  1. 需要在父进程中声明多进程主程序,即:

    if __name__ == '__main__':
    
  2. 需要使用 if __name__ == '__main__': 语句将多进程执行的程序包裹起来,确保只有主进程执行主线程的代码,子进程只执行自己的代码。

  3. 需要注意在 multiprocessing.Process 中传递函数的参数。有三种方式:

    • 使用全局变量
    • multiprocessing.Process 中传递参数,如 target=func, args=(arg1,arg2,)
    • 使用 multiprocessing.Manager 模块的共享内存方式,如:manager=Manager(), queue=manager.Queue()

根据你的描述,可能存在以下几个问题:

  1. 没有在父进程中声明多进程主程序,你需要加上 if __name__ == '__main__': 语句将多进程执行的程序包裹起来。

  2. 可能因为多进程共享数据的问题,导致传入函数的参数不正确。你需要检查一下参数的传递方式是否正确,建议使用 multiprocessing.Manager 模块的共享内存方式来解决。

以下是修改后的代码:

import multiprocessing
from multiprocessing import Manager

def map():
    ...

def wind_shear(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time):
    ...

def draw_w(ds, lon_range, lat_range, lon, lat, lons, lats, time, ds_time):
    ...

def f1(hours, ds, lon_range, lat_range, lon, lat, lons, lats, time):
    for hour in hours:
        ds_time = '%s-%s-%sT%s'%(year, month, day, hour)
        wind_shear(ds, lon_range, lat_range, lons, lats, time, ds_time)

def f2(hours, ds, lon_range, lat_range, lon, lat, lons, lats, time):
    for hour in hours:
        ds_time = '%s-%s-%sT%s'%(year, month, day, hour)
        draw_w(ds, lon_range, lat_range, lons, lats, time, ds_time)

if __name__ == '__main__':
    map()
    manager = Manager()
    queue = manager.Queue()
    for i in j:
        ...
        ...
        time = ...
        hours = ...
        ds1 = ...
        ds = ...
        lon = ...
        lat = ...
        lon_range = ...
        lat_range = ...
        lons,lats = ...
        lon_2d, lat_2d = ...
        lon_2d[lon_2d > 180] = ...
        p1 =  multiprocessing.Process(target=f1, args=(hours, ds, lon_range, lat_range, lon, lat, lons, lats, time))
        p2 =  multiprocessing.Process(target=f2, args=(hours, ds, lon_range, lat_range, lon, lat, lons, lats, time))

        p1.start()
        p2.start()

        p1.join()
        p2.join()

注意,在 args 中排序要与函数参数列表顺序一致。
如果我的回答解决了您的问题,请采纳!