Skip to main content
 首页 » 编程设计

Python 多处理 map_async ready() 和 _number_left 未按预期工作

2025年05月04日28mate10pro

这有点复杂,我确信这是一个新手错误,但我终究无法弄清楚该往哪里看。

尝试执行多处理 map_async 来处理大量文件。本质上,该代码获取文件列表,在每个文件中查找 MAC 地址的匹配项,如果匹配,则将一行写到另一个文件。

nodb 是我的图书馆....我还没有把所有的东西都包括在这里(这有点令人费解)。我希望有人可以指出我在哪里可以调试它。

这就是问题所在:代码在 60,000 个文件以下的任何文件上都能完美运行。然而,当我将它指向一个包含 595,200 个文件的目录时,检查是否完成(使用 _number_left)的小“while true”循环停止工作....处理似乎继续但 _number_left 并没有减少并且ready() 函数返回 TRUE...但事实并非如此。

每次我运行它时,它都会在处理 62111 或 62112 个文件后停止。我添加了一个小的“转储”功能,以为我的队列已满。

不知道还能告诉你什么……我是不是漏掉了什么? (可能)请让我知道我还能告诉你什么来解决这个问题。我真的不知道什么是相关的....

代码是:

import nodb_v09d as nodb 
 
import netaddr 
import sys 
import collections 
from multiprocessing import Pool, Queue 
import itertools 
import time 
 
# Handle CLI arguments 
# 
nmultip = 1 
args = sys.argv[1:] 
nmultip = nodb.parseArgs(args) 
 
# this function just gets the file list in the directory 
todoPif = nodb.getFileList('/data/david/data/2012/05') 
 
filterfields = { 10:set([int(netaddr.EUI('00-00-0a-0e-c9-be')),\ 
                         int(netaddr.EUI('00:15:ce:de:78:f3')),\ 
                         int(netaddr.EUI('3c-75-4a-ea-15-01')),\ 
                         int(netaddr.EUI('00-24-d1-1e-e9-be'))]) 
                 } 
ff=collections.OrderedDict(sorted(filterfields.items())) 
 
resultfields = [28,29,30,33] 
rf=resultfields.sort 
 
cutoff = 40 
 
todocnt = len(todoPif) 
 
outQ = Queue() 
hdrQ = Queue() 
 
# output file 
gpif = '/media/sf_samplePifs/test2.gpif' 
 
append = 0 
 
if __name__ == '__main__': 
 
    # this is a little trick I picked up off the internet for passing multiple queues.  works ok 
    todopool = Pool(None,nodb.poolQueueInit,[outQ,hdrQ]) 
 
    # itertools used to create an arg that contains a constant (ff) for all calls) 
    r = todopool.map_async(nodb.deRefCall,itertools.izip(todoPif, itertools.repeat(ff)),1) 
 
    while (True): 
        nodb.logging.info('number left: ' + str(r._number_left) + '\nready? ' + str(r.ready())) 
        nodb.logging.info('queue size: ' + str(outQ.qsize())) 
 
        if (r._number_left == 0): break 
        if (outQ.qsize() >= cutoff): 
            nodb.dumpQueueToGpif(gpif, hdrQ, outQ, append, cutoff) 
            if (append == 0):  
                append = 1 
 
        sys.stderr.write('\rPIF Files DONE: ' + str(todocnt-r._number_left) + '/' + str(todocnt)) 
        print '\n' 
        time.sleep(0.2) 
    r.wait()   
 
sys.stderr.write('\rPIF Files DONE: ' + str(todocnt) + '/' + str(todocnt) + '\n') 
 
# dump remainder to file 
nodb.dumpQueueToGpif(gpif, hdrQ, outQ, append,outQ.qsize()) 

主要补充:

应另一位用户的要求,我简化了代码。没有队列,没有外部私有(private)库等:

import sys 
import os 
import time 
from multiprocessing import Pool 
 
def doPifFile(pifFile): 
 
    #readPif = call(['ls','-l',' > /tmp/out']) 
    cmd = 'ipdr_dump ' + pifFile + ' | grep "," | wc -l > /tmp/dump' 
    readPif = os.system(cmd) 
    return readPif 
 
def getFileList(directory): 
    flist = list() 
    for root, dirs, files in os.walk(directory): 
        for piffile in files: 
            if piffile.endswith('.pif'): 
                flist.append(os.path.abspath(os.path.join(root,piffile))) 
    return flist 
 
todoPif = getFileList('/data/david/data/2012/05') 
 
todocnt = len(todoPif) 
print '# of files to process: ' + str(todocnt) 
 
if __name__ == '__main__': 
 
    todopool = Pool() 
    r = todopool.map_async(doPifFile,todoPif,1) 
 
    while (True): 
        print 'number left: ' + str(r._number_left) + '\nready? ' + str(r.ready()) 
 
        #if (r.ready()): break 
        if (r._number_left == 0): break 
        sys.stderr.write('\rPIF Files DONE: ' + str(todocnt-r._number_left) + '/' + str(todocnt)) 
        print '\n' 
        time.sleep(0.2) 
 
sys.stderr.write('\rPIF Files DONE: ' + str(todocnt) + '/' + str(todocnt) + '\n') 

当我运行它时,我得到了一些非常有趣的东西,虽然它声称它发生在我的转储程序中,但在运行更复杂的代码时并没有出现,而是发生在完全相同的位置:

number left: 533100 
ready? False 
PIF Files DONE: 62100/595200 
 
number left: 533090 
ready? False 
PIF Files DONE: 62110/595200 
 
*** glibc detected *** ipdr_dump: corrupted double-linked list: 0x0000000001a58370 *** 
======= Backtrace: ========= 
/lib64/libc.so.6[0x36f5c76126] 
/lib64/libc.so.6[0x36f5c78eb4] 
/lib64/libc.so.6(fclose+0x14d)[0x36f5c6678d] 
/lib64/libz.so.1[0x36f6803021] 
ipdr_dump[0x405c0b] 
ipdr_dump[0x40546e] 
ipdr_dump[0x401c2a] 
/lib64/libc.so.6(__libc_start_main+0xfd)[0x36f5c1ecdd] 
ipdr_dump[0x4016b9] 
======= Memory map: ======== 
00400000-0040e000 r-xp 00000000 08:02 2364135                            /home/david/ipdr_dump 
0060d000-0060e000 rw-p 0000d000 08:02 2364135                            /home/david/ipdr_dump 
01a54000-01a75000 rw-p 00000000 00:00 0                                  [heap] 
32e0600000-32e0604000 r-xp 00000000 08:02 3932181                        /lib64/libuuid.so.1.3.0 
32e0604000-32e0803000 ---p 00004000 08:02 3932181                        /lib64/libuuid.so.1.3.0 
32e0803000-32e0804000 rw-p 00003000 08:02 3932181                        /lib64/libuuid.so.1.3.0 
36f5800000-36f5820000 r-xp 00000000 08:02 3932309                        /lib64/ld-2.12.so 
36f5a1f000-36f5a20000 r--p 0001f000 08:02 3932309                        /lib64/ld-2.12.so 
36f5a20000-36f5a21000 rw-p 00020000 08:02 3932309                        /lib64/ld-2.12.so 
36f5a21000-36f5a22000 rw-p 00000000 00:00 0  
36f5c00000-36f5d8a000 r-xp 00000000 08:02 3932315                        /lib64/libc-2.12.so 
36f5d8a000-36f5f89000 ---p 0018a000 08:02 3932315                        /lib64/libc-2.12.so 
36f5f89000-36f5f8d000 r--p 00189000 08:02 3932315                        /lib64/libc-2.12.so 
36f5f8d000-36f5f8e000 rw-p 0018d000 08:02 3932315                        /lib64/libc-2.12.so 
36f5f8e000-36f5f93000 rw-p 00000000 00:00 0  
36f6000000-36f6002000 r-xp 00000000 08:02 3932566                        /lib64/libdl-2.12.so 
36f6002000-36f6202000 ---p 00002000 08:02 3932566                        /lib64/libdl-2.12.so 
36f6202000-36f6203000 r--p 00002000 08:02 3932566                        /lib64/libdl-2.12.so 
36f6203000-36f6204000 rw-p 00003000 08:02 3932566                        /lib64/libdl-2.12.so 
36f6400000-36f6417000 r-xp 00000000 08:02 3932564                        /lib64/libpthread-2.12.so 
36f6417000-36f6617000 ---p 00017000 08:02 3932564                        /lib64/libpthread-2.12.so 
36f6617000-36f6618000 r--p 00017000 08:02 3932564                        /lib64/libpthread-2.12.so 
36f6618000-36f6619000 rw-p 00018000 08:02 3932564                        /lib64/libpthread-2.12.so 
36f6619000-36f661d000 rw-p 00000000 00:00 0  
36f6800000-36f6815000 r-xp 00000000 08:02 3932563                        /lib64/libz.so.1.2.3 
36f6815000-36f6a14000 ---p 00015000 08:02 3932563                        /lib64/libz.so.1.2.3 
36f6a14000-36f6a15000 r--p 00014000 08:02 3932563                        /lib64/libz.so.1.2.3 
36f6a15000-36f6a16000 rw-p 00015000 08:02 3932563                        /lib64/libz.so.1.2.3 
36f6c00000-36f6c83000 r-xp 00000000 08:02 3932493                        /lib64/libm-2.12.so 
36f6c83000-36f6e82000 ---p 00083000 08:02 3932493                        /lib64/libm-2.12.so 
36f6e82000-36f6e83000 r--p 00082000 08:02 3932493                        /lib64/libm-2.12.so 
36f6e83000-36f6e84000 rw-p 00083000 08:02 3932493                        /lib64/libm-2.12.so 
36f7000000-36f7007000 r-xp 00000000 08:02 3935994                        /lib64/librt-2.12.so 
36f7007000-36f7206000 ---p 00007000 08:02 3935994                        /lib64/librt-2.12.so 
36f7206000-36f7207000 r--p 00006000 08:02 3935994                        /lib64/librt-2.12.so 
36f7207000-36f7208000 rw-p 00007000 08:02 3935994                        /lib64/librt-2.12.so 
36f7800000-36f781d000 r-xp 00000000 08:02 3932588                        /lib64/libselinux.so.1 
36f781d000-36f7a1c000 ---p 0001d000 08:02 3932588                        /lib64/libselinux.so.1 
36f7a1c000-36f7a1d000 r--p 0001c000 08:02 3932588                        /lib64/libselinux.so.1 
36f7a1d000-36f7a1e000 rw-p 0001d000 08:02 3932588                        /lib64/libselinux.so.1 
36f7a1e000-36f7a1f000 rw-p 00000000 00:00 0  
36f7c00000-36f7c16000 r-xp 00000000 08:02 3932572                        /lib64/libresolv-2.12.so 
36f7c16000-36f7e16000 ---p 00016000 08:02 3932572                        /lib64/libresolv-2.12.so 
36f7e16000-36f7e17000 r--p 00016000 08:02 3932572                        /lib64/libresolv-2.12.so 
36f7e17000-36f7e18000 rw-p 00017000 08:02 3932572                        /lib64/libresolv-2.12.so 
36f7e18000-36f7e1a000 rw-p 00000000 00:00 0  
36f8000000-36f800e000 r-xp 00000000 08:02 3935998                        /lib64/liblber-2.4.so.2.5.6 
36f800e000-36f820d000 ---p 0000e000 08:02 3935998                        /lib64/liblber-2.4.so.2.5.6 
36f820d000-36f820e000 r--p 0000d000 08:02 3935998                        /lib64/liblber-2.4.so.2.5.6 
36f820e000-36f820f000 rw-p 0000e000 08:02 3935998                        /lib64/liblber-2.4.so.2.5.6 
36f8800000-36f8849000 r-xp 00000000 08:02 3932243                        /lib64/libldap-2.4.so.2.5.6 
36f8849000-36f8a49000 ---p 00049000 08:02 3932243                        /lib64/libldap-2.4.so.2.5.6 
36f8a49000-36f8a4b000 r--p 00049000 08:02 3932243                        /lib64/libldap-2.4.so.2.5.6 
36f8a4b000-36f8a4d000 rw-p 0004b000 08:02 3932243                        /lib64/libldap-2.4.so.2.5.6 
36f8c00000-36f8c16000 r-xp 00000000 08:02 3936000                        /lib64/libgcc_s-4.4.7-20120601.so.1 
36f8c16000-36f8e15000 ---p 00016000 08:02 3936000                        /lib64/libgcc_s-4.4.7-20120601.so.1 
36f8e15000-36f8e16000 rw-p 00015000 08:02 3936000                        /lib64/libgcc_s-4.4.7-20120601.so.1 
36f9400000-36f9535000 r-xp 00000000 08:02 4206136                        /usr/lib64/libnss3.so 
36f9535000-36f9734000 ---p 00135000 08:02 4206136                        /usr/lib64/libnss3.so 
36f9734000-36f9739000 r--p 00134000 08:02 4206136                        /usr/lib64/libnss3.so 
36f9739000-36f973b000 rw-p 00139000 08:02 4206136                        /usr/lib64/libnss3.so 
36f973b000-36f973d000 rw-p 00000000 00:00 0  
36f9800000-36f9825000 r-xp 00000000 08:02 4206135                        /usr/lib64/libnssutil3.so 
36f9825000-36f9a24000 ---p 00025000 08:02 4206135                        /usr/lib64/libnssutil3.so 
36f9a24000-36f9a2a000 r--p 00024000 08:02 4206135                        /usr/lib64/libnssutil3.sonumber left: 533078 
ready? False 
PIF Files DONE: 62122/595200 
 
number left: 533068 
ready? False 
PIF Files DONE: 62132/595200 
 
number left: 533056 
ready? False 
PIF Files DONE: 62144/595200 

奇怪的是它继续运行,而之前的运行导致 _number_left 失败并在“ready()”上失火(尽管进程仍在后台运行)。

我已经在我拥有的 16 处理器盒上手动运行了转储程序,它们并行运行良好,之前从未见过 glibc 错误。我必须假设它与 python 设置有关....我只是不知道在哪里。

这对于论坛诊断来说可能太复杂了。欢迎任何关于我可能会看到的地方或我如何能够看起来发生了什么的进一步想法。

还有一个花絮...打印出 pool._success。它在 _number_left 停止移动的神奇时刻变为 FALSE。

INFO  number left: 533167   
ready? False   
successful? True   
INFO  queue size: 424   
PIF Files DONE: 62033/595200   
 
INFO  number left: 533117 
ready? False 
successful? True 
INFO  queue size: 424 
PIF Files DONE: 62083/595200 
 
INFO  number left: 533087 
ready? True 
successful? False 
INFO  queue size: 424 
PIF Files DONE: 62113/595200 
 
INFO  number left: 533087 
ready? True 
successful? False 
INFO  queue size: 424 
PIF Files DONE: 62113/595200 

请您参考如下方法:

折腾了半天,终于找到问题了....至于是什么原因,暂时还说不准。看起来像一个错误。

这里有几个高级命令,所以我接下来解释的内容更有意义(这并不意味着可执行):

todopool = Pool() 
 
r = todopool.map_async(myfunction,args,1) 
 
print type(r._value) 

回想一下,args 是一个包含 595,200 个文件名的列表。

我开始查看 r._value,在我的例子中它是一个长度为 595,200 的列表。我注意到在问题出现的地方,值发生了变化....所以我查看了类型。

这是我最近运行的输出:

INFO  number left: 533148 <- based on r._number_left 
<type 'list'>             <- print type(r._value) 
PIF Files DONE: 62052/595200 
 
INFO  number left: 533096 
<type 'list'> 
PIF Files DONE: 62104/595200 
 
INFO  number left: 533087 
<class 'nodb_v09e.pifReaderEOFReached'> 
PIF Files DONE: 62113/595200 
 
INFO  number left: 533087 
<class 'nodb_v09e.pifReaderEOFReached'> 
PIF Files DONE: 62113/595200 

突然间,长度为 595,200 的列表 r._value 现在变成了异常类。奇怪的是我的子程序的每次运行都以那个异常结束,所以这个特定的运行与任何其他运行没有什么不同......这是我告诉我在文件末尾的方式。

将 r._value 从列表更改为类是搞砸 _number_left 和我的结果反馈显示的原因。为什么这样做尚未确定。