我有一些使用pandas
的Python代码,运行大约需要半秒钟。当我连续5次调用main函数(在一个线程上)时,每次调用大约需要半秒钟,因此总共需要2.5秒。但是,当我在5个不同的线程上调用此函数时,每次运行需要2.5秒(总共也是2.5秒,但我预计它总共只有半秒,因为线程并行运行)。
代码基本上是这样做的(简化为了简洁起见):
from pandas.io.json import json_normalize
import pandsas as pd
def build_df():
event_type_0_lst = {'a': 1, 'b':{'c': 2}}
event_type_1_lst = {'d': 4, 'e':{'f': 5}}
event_type_2_lst = {'g': 7, 'h':{'i': 8}}
type_0_df = pd.DataFrame()
type_1_df = json_normalize(event_type_1_lst)
type_1_df[self.event_source_col] = self.event_type_1
type_2_df = json_normalize(event_type_2_lst)
type_2_df[self.event_source_col] = self.event_type_2
all_data_df = pd.concat([type_0_df, type_1_df, type_2_df])
final_df = all_data_df[
[self.ticket_col, self.timestamp_col, self.trigger_col, self.action_col,
self.action_uid_col, self.msg_id_col, self.flc_col, self.event_source_col]]
final_df[self.timestamp_col] = pd.to_datetime(final_df[self.timestamp_col])
return ticket_df.sort_values(self.timestamp_col).reset_index(drop=True)
def normalize(df):
df.columns = [col.replace('.', '_') for col in df.columns]
for col in df.columns:
df[col] = df[col].astype(str)
df[col] = df[col].str.encode('unicode-escape').replace('\\x', '<repl>')
df[col] = df[col].str.encode('unicode-escape').replace('\n', '<repl>')
return df
def handle_request():
df = build_df()
return normalize(df)
可以从Web服务器(使用handle_request
包的ThreadPoolExecutor)或从独立的python脚本调用函数concurrent.futures
(使用threading
包和标准方法创建线程),并在两种情况下重现该问题。我运行此功能的机器有8个核心,应该足够5个线程。
当我运行此功能时,我收到以下警告:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
FutureWarning: sort(columns=....) is deprecated, use sort_values(by=.....)
df_sorted = df.sort(col_order_by, ascending=True)
我认为它与此问题没有任何关联,但我会将其粘贴以防万一。
那么,为什么每次运行需要大约2.5秒而不是〜0.5?
编辑:这就是我使用threading
运行该函数的方法:
threads_list = []
for i in range(num_of_threads):
t = threading.Thread(target=handle_request)
threads_list.append(t)
for t in threads_list:
t.start()
我尝试添加:
for t in threads_list:
t.join()
但它似乎对表现没有任何影响。
答案 0 :(得分:0)
问题是,如this blog post中所述,“ CPython解释器上的Python不支持通过多线程进行真正的多核执行。”
使用threading
库而不是使用multiprocessing
库。在下面的示例中,我所做的只是用对multiprocessing
库的调用替换了您的代码。但是,这种方法有一些警告。您将需要使用与multiprocessing
库一起使用的实用程序来管理进程之间的通信。 (例如,我很好地利用了multiprocessing.Queue
类。)
import multiprocessing
processes_list = []
for _ in range(num_of_processes):
processes_list.append(multiprocessing.Process(target=handle_request))
for p in processes_list:
p.start()