我有一个Flask服务器,它对数据帧执行读写查询。我有一个缓存机制(使用缓存库)来在接收请求时缓存数据帧,然后在接收到对同一数据帧的请求时使用缓存的数据帧。
当前,我正在使用一个锁,该锁使所有线程依次加载其(不同的)数据帧,然后进一步处理加载的数据帧。
我想要的是,当我收到多个针对不同数据帧的请求时,每个线程(针对每个请求)应将数据帧(使用pandas.read_excel)同时加载到内存中,而不是顺序加载。
当前,我正在使用一个简单的锁,以确保同一数据帧不会被加载两次,但是我还需要并行加载多个数据帧。
`def read_query_request(查询,文件路径,工作表名称,源ID): logger.info('处理对源的读取请求'+ sheet_name +'_'+ source_id)
try:
data_frame_identifier = sheet_name + '_' + source_id
# Load df with lock ensuring data frame loads only once.
with lock:
start_l=time.time()
load_data_frame(file_path, sheet_name, source_id)
end_l=time.time()
logger.info('BENCHMARKING INFO: Read Request, Data frame load time ---' + str(end_l - start_l))
#cache_state()
# Executing query on loaded data frame
# sheetName = getSheetName( query )
query = query.replace('dataframe', data_frame_identifier)
start_e = time.time()
queryResult = ps.sqldf(query)
end_e = time.time()
logger.info('BENCHMARKING INFO: Read Request, psql query execution time ---' + str(end_e - start_e))
start_j = time.time()
queryResult = queryResult.to_json(orient='records')
res = {"isErrored":"False", "results": json.loads(queryResult)}
result = json.dumps(res)
end_j = time.time()
logger.info('BENCHMARKING INFO: Read Request, json conversion time ---' + str(end_j - start_j))
logger.info(LRU_cache.keys())
return result`
答案 0 :(得分:0)
据我从您的代码中了解到,您正在为整个应用程序使用一个锁,这限制了一次只能处理一个数据帧,并且您希望并行处理多个。首先,Python中的线程(由于GIL)不能并行运行,而是按顺序运行。因此,如果要并行执行,则需要进行多次处理。实现最简单的方法是使用stdlib的multiprocessing pool。但是您仍然需要进行一些同步,以避免一次处理多个df。为此,您可以保留当前正在处理的df的注册表:
...
registry_change_lock = Lock()
registry = set() # you can use list, but search in list is O(n) and in set is O(1)
while True:
registry_change_lock.acquire()
if source_id in registry:
# This id is already processed, release the lock
# to let other threads register their ids and avoid
# deadlocks
registry_change_lock.release()
time.sleep(0.5)
continue
else:
registry.add(source_id)
registry_change_lock.release()
P.S。这不是解决问题的唯一方法,而是更简单的方法之一。