Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 在多线程应用程序中,在何处设置锁?_Python 3.x_Multithreading_Pandas_Multiprocessing_Apply - Fatal编程技术网

Python 3.x 在多线程应用程序中,在何处设置锁?

Python 3.x 在多线程应用程序中,在何处设置锁?,python-3.x,multithreading,pandas,multiprocessing,apply,Python 3.x,Multithreading,Pandas,Multiprocessing,Apply,我正在尝试使用apply函数异步读取和写入数据。为此,我使用了多线程.dummy包。由于我在df上同时执行读写操作(多线程),因此我使用了多处理.Lock(),这样在给定时间内最多只能有一个线程可以编辑df。然而,我有点困惑,我应该在哪里添加一个lock.acquire()和lock.release()以及pandas中的apply函数。我试着按照下面的方法来做,但是,这样做似乎会使整个过程变得同步,因此它违背了多线程的全部目的 self._lock.acquire() to_df[col_na

我正在尝试使用apply函数异步读取和写入数据。为此,我使用了
多线程.dummy
包。由于我在df上同时执行读写操作(多线程),因此我使用了
多处理.Lock()
,这样在给定时间内最多只能有一个
线程
可以编辑df。然而,我有点困惑,我应该在哪里添加一个
lock.acquire()
lock.release()
以及
pandas
中的
apply
函数。我试着按照下面的方法来做,但是,这样做似乎会使整个过程变得
同步
,因此它违背了多线程的全部目的

self._lock.acquire()
to_df[col_name] = to_df.apply(lambda row: getattr(Object(row['col_1'], 
                                                           row['col_2'],
                                                           row['col_3']), 
                                                          someattribute), axis=1)
self._lock.release()

注意:在我的情况下,我必须执行
getattr
someattribute
只是
对象中的
@属性
。对象接受3个参数,其中一些参数来自我的df的第1、2、3行。

有两种可能的解决方案。1-锁。2-排队。下面的代码只是一个框架,可能包含打字错误,不能按原样使用

首先。在实际需要的地方锁定:

def method_to_process_url(df):

    lock.acquire()
    url = df.loc[some_idx, some_col]
    lock.release()

    info = process_url(url)

    lock.acquire()
    # add info to df
    lock.release()
第二。队列而不是锁:

def method_to_process_url(df, url_queue, info_queue):
    for url in url_queue.get():
        info = process_url(url)
        info_queue.put(info)

url_queue = queue.Queue()
# add all urls to process to the url_queue

info_queue = queue.Queue()

# working_thread_1
threading.Thread(
    target=method_to_process_url,
    kwargs={'url_queue': url_queue, 'info_queue': info_queue},
    daemon=True).start()


# more working threads

counter = 0
while counter < amount_of_urls:
    info = info_queue.get():
    # add info to df
    counter += 1
def方法到过程url(df、url队列、信息队列):
对于url_队列中的url.get():
info=进程\ url(url)
信息队列。放置(信息)
url\u queue=queue.queue()
#将要处理的所有url添加到url\u队列
info_queue=queue.queue()
#工作螺纹1
穿线,穿线(
目标=方法到进程的url,
kwargs={'url\u queue':url\u queue,'info\u queue':info\u queue},
daemon=True)
#更多的工作线程
计数器=0
当计数器
在第二种情况下,您甚至可以为每个url启动单独的线程,而不使用
url\u queue
(如果url的数量在数千个或更少的顺序上,这是合理的)<代码>计数器是在处理所有URL时停止程序的简单方法


如果你问我,我会使用第二种方法。在我看来,它更灵活。

异步执行的最初目的是什么?在Python(CPython)中,线程用于I/O绑定的操作(由于GIL),进程用于CPU绑定的操作。@Poolka所以我使用的Panda包含URL列,对于每个URL,它会调用不同的位置,然后将信息返回给DFT,然后更改设计-使用线程和队列将URL发送给工作线程,并将信息返回给主线程以将其合并到df中。锁是不需要的。@Poolka你会怎么做?我会把你的答案标记为正确的,但是,正如我发现的,熊猫在线程时是不安全的。看看这个。请看警告下的警告。@callmeGuy这根本不是问题。这些方法中的安全性是通过锁/队列实现的(锁是锁,队列是线程安全的)。在第二种方法中,数据帧仅在一个线程中处理。