python多处理卡住了(也许正在读取csv)

时间:2018-08-17 18:20:41

标签: python pandas multiprocessing

我正在尝试学习如何使用multiprocessing,但遇到了问题。

我正在尝试运行以下代码:

import multiprocessing as mp
import random
import string

random.seed(123)

# Define an output queue
output = mp.Queue()

# define a example function
def rand_string(length, output):
    """ Generates a random string of numbers, lower- and uppercase chars. """
    rand_str = ''.join(random.choice(
                        string.ascii_lowercase
                        + string.ascii_uppercase
                        + string.digits)
                   for i in range(length))
    output.put(rand_str)

# Setup a list of processes that we want to run
processes = [mp.Process(target=rand_string, args=(5, output)) for x in range(4)]

# Run processes
for p in processes:
    p.start()

# Exit the completed processes
for p in processes:
    p.join()

# Get process results from the output queue
results = [output.get() for p in processes]

print(results)

来自here

代码本身可以正常运行,但是当我用函数替换rand_string(在Pandas数据帧中读取一堆csv文件)时,代码永无休止。

功能是这样的:

def readMyCSV(clFile):

    aClTable = pd.read_csv(clFile)

    # I do some processing here, but at the end the 
    # function returns a Pandas DataFrame

    return(aClTable)

然后,我包装函数,使其在参数中允许Queue

def readMyCSVParWrap(clFile, outputq):
    outputq.put(readMyCSV(clFile))

然后我用以下方法构建流程:

processes = [mp.Process(target=readMyCSVParWrap, args=(singleFile,output)) for singleFile in allFiles[:5]]

如果这样做,代码将永远不会停止运行,并且永远不会打印结果。

如果我仅将clFile字符串放入输出队列中,例如:

outputq.put((clFile))

结果正确打印(只是clFiles列表)

当我查看htop时,看到有5个进程正在生成,但是它们不使用任何CPU。

最后,如果我自己运行readMyCSV函数(返回Pandas DataFrame),则该函数正常工作

我在做错什么吗? 我正在Jupyter笔记本中运行此程序,也许是个问题吗?

1 个答案:

答案 0 :(得分:1)

似乎您在进程上的join语句正在导致死锁。进程无法终止,因为它们要等到队列中的项目被消耗完为止,但是在您的代码中,这只会在加入之后发生。

  

使用队列的加入过程

     

请记住,将项目放入队列的进程将在终止之前等待,直到所有缓冲的项目由“ feeder”线程馈送到基础管道为止。 (子进程可以调用队列的Queue.cancel_join_thread方法来避免这种行为。)

     

这意味着,每当您使用队列时,都需要确保在加入该进程之前,将最终删除队列中已放置的所有项目。否则,您无法确定将项目放入队列的进程将终止。还请记住,非守护进程将自动加入。   docs

文档进一步建议将行与queue.getjoin交换,或者仅删除join

也很重要:

  

确保可以通过新的Python解释器安全地导入主模块,而不会引起意外的副作用(例如,启动新进程)...通过使用if 名称来保护程序的“入口点” =='主要':。 ibid