为什么多处理池的实现不起作用?

时间:2015-04-03 05:59:53

标签: python multithreading pandas

以下是我正在使用的代码:

import pandas as pd
import sys, multiprocessing

train_data_file = '/home/simon/ali_bigdata/train_data_user_2.0.csv'
user_list_file = '/home/simon/ali_bigdata/user_list.txt'



def feature_extract(list_file, feature_extract_func):
    tmp_list = [line.strip() for line in open(list_file)]

    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    results_list = pool.map(feature_extract_func, tmp_list)

    for tmp in results_list:
        for i in tmp:
            print i,"\t",
        print "\n"

    pool.close()
    pool.join()

def user_feature(tmp_user_id):
    sys.stderr.write("process user " + tmp_user_id + " ...\n")
    try:
        tmp_user_df = df_user.loc[int(tmp_user_id)]
    except KeyError:
        return [tmp_user_id, 0, 0, 0.0]
    else:
        if type(tmp_user_df) == pd.core.series.Series:
            tmp_user_click = 1
        else:
            (tmp_user_click, suck) = tmp_user_df.shape

        tmp_user_buy_df = tmp_user_df.loc[tmp_user_df['behavior_type'] == 4]
        if type(tmp_user_buy_df) == pd.core.frame.DataFrame:
            tmp_user_buy = 1
        else:
            (tmp_user_buy, suck) = tmp_user_buy_df.shape


        return [tmp_user_id, tmp_user_click, tmp_user_buy, 0.0 if tmp_user_click == 0 else float(tmp_user_buy)/tmp_user_click]


df = pd.read_csv(train_data_file, header=0)
df_user = df.set_index(['user_id'])
feature_extract(user_list_file, user_feature)

我得到的错误是:

process user 102761946 ...
process user 110858443 ...
process user 131681429 ...
Traceback (most recent call last):
  File "extract_feature_2.0.py", line 53, in <module>
    feature_extract(user_list_file, user_feature)
  File "extract_feature_2.0.py", line 13, in feature_extract
    results_list = pool.map(feature_extract_func, tmp_list)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
    raise self._value
KeyError: 'the label [False] is not in the [index]'

当程序运行一段时间时会发生。

那么这个错误意味着什么?如何对这个地图函数进行多处理呢?

这里是输入数据格式

user_id,item_id,behavior_type,user_geohash,item_category,date,time
99512554,37320317,3,94gn6nd,9232,2014-11-26,20
9909811,266982489,1,,3475,2014-12-02,23
98692568,27121464,1,94h63np,5201,2014-11-19,13

2 个答案:

答案 0 :(得分:0)

很难在多处理中使用的函数内调试错误。您应该关闭多处理以对其进行调试,然后在修复时将其重新打开。我的函数中通常有一个mp=True参数,默认情况下在多处理模式下运行该函数,但可以设置为False以使用常规的非多处理map运行它(使用if测试)所以我可以调试这些错误。

所以你可以像这样设置你的函数,并用mp=False参数运行它来调试它:

def feature_extract(list_file, feature_extract_func, mp=True):
    tmp_list = [line.strip() for line in open(list_file)]

    if mp:
        pool = multiprocessing.Pool(multiprocessing.cpu_count())
        results_list = pool.map(feature_extract_func, tmp_list)
    else:
        results_list = map(feature_extract_func, tmp_list)

    for tmp in results_list:
        for i in tmp:
            print i,"\t",
        print "\n"

    if mp:
        pool.close()
        pool.join()

此外,Pool默认情况下会自动使用可用的cpus数,因此您不需要设置进程数,除非您想要不同的进程。

此外,在这种情况下使用生成器表达式而不是列表解析更高效(尽管您可以更轻松地对列表理解进行切片,因此对于调试,您可能希望使用列表推导来跳转到导致问题的索引):

因此,一旦调试完成,请替换:

tmp_list = [line.strip() for line in open(list_file)]

使用:

tmp_list = (line.strip() for line in open(list_file))

答案 1 :(得分:0)

发生错误时,您尚未显示正在播放的任何数据。请在您的问题中发布触发问题的代表性数据 - 如果您的问题可以重现,将会更容易帮助您。

我认为错误发生在这一行:

tmp_user_buy_df = tmp_user_df.loc[tmp_user_df['behavior_type'] == 4]

tmp_user_df['behavior_type'] == 4返回一个布尔值 - True或False - 然后用作标签。由于标签False不是数据框/标签KeyError: 'the label [False] is not in the [index]'中的标签。我很困惑为什么True案例显然有用,但后来我们没有看到你的数据,所以可能会有解释。

您可能打算将布尔数组作为选择器传递;如果是,则将行为类型查找包装在列表中,例如:

tmp_user_buy_df = tmp_user_df.loc[[tmp_user_df['behavior_type'] == 4]]

另外,isinstance()type(x) == X更受欢迎,请参阅this comprehensive explanation,您可以更改行

if type(tmp_user_df) == pd.core.series.Series:

if isinstance(tmp_user_df, pd.core.series.Series):

if type(tmp_user_buy_df) == pd.core.frame.DataFrame:

if isinstance(tmp_user_buy_df, pd.core.frame.DataFrame):