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 如何在保持订单的同时在生成器上使用线程(每个项目有多个线程)?_Python_Multithreading_Python 2.7_Python Multithreading - Fatal编程技术网

Python 如何在保持订单的同时在生成器上使用线程(每个项目有多个线程)?

Python 如何在保持订单的同时在生成器上使用线程(每个项目有多个线程)?,python,multithreading,python-2.7,python-multithreading,Python,Multithreading,Python 2.7,Python Multithreading,我有一个模仿RESTAPI调用的代码(见下文) 对于生成器项中的每个键,它都需要运行REST调用。所以在我的例子中,记录可以是 {"a": 2, "b": 36, "c": 77} 我需要分别为每个键(a、b、和c)运行一个REST调用,然后输出结果(这只是对数字求反): 现在我当前的代码只适用于一个键,但如果有多个键,它将重复这些项(因此我得到了三个键的结果) 此外,也出现了一些令人生厌的种族状况。我想我只能保留最后一条记录,但我不擅长线程,担心线程安全或其他高级东西 以下是一个示例输出:

我有一个模仿RESTAPI调用的代码(见下文)

对于生成器项中的每个键,它都需要运行REST调用。所以在我的例子中,记录可以是

{"a": 2, "b": 36, "c": 77}
我需要分别为每个键(
a
b
、和
c
)运行一个REST调用,然后输出结果(这只是对数字求反):

现在我当前的代码只适用于一个键,但如果有多个键,它将重复这些项(因此我得到了三个键的结果)

此外,也出现了一些令人生厌的种族状况。我想我只能保留最后一条记录,但我不擅长线程,担心线程安全或其他高级东西

以下是一个示例输出:

{'a': 89, 'a_neg': -89, 'b': 69, 'c': 38}
{'a': 89, 'a_neg': -89, 'b': 69, 'c': 38, 'c_neg': -38}
{'a': 89, 'a_neg': -89, 'b': 69, 'b_neg': -69, 'c': 38, 'c_neg': -38}
{'a': 90, 'a_neg': -90, 'b': 43, 'c': 16}
{'a': 90, 'a_neg': -90, 'b': 43, 'c': 16, 'c_neg': -16}
{'a': 90, 'a_neg': -90, 'b': 43, 'b_neg': -43, 'c': 16, 'c_neg': -16}
{'a': 91, 'a_neg': -91, 'b': 49, 'b_neg': -49, 'c': 77, 'c_neg': -77}
{'a': 91, 'a_neg': -91, 'b': 49, 'b_neg': -49, 'c': 77, 'c_neg': -77}
{'a': 91, 'a_neg': -91, 'b': 49, 'b_neg': -49, 'c': 77, 'c_neg': -77}
最后,这里是我的源代码(您可以自己运行):


这里的第一个问题是,在一个不断增长的记录中循环键

for key in list(record):  # make a copy of the keys!
我认为这里的第二个问题是你有3个键和8个线程<代码>长度(块)将是
3、6、9
<代码>线程为
8
-未达到以下条件

        if len(chunk) == threads:  # try len(chunk) >= threads
            yield chunk
            chunk = []
最后一个问题是,在所有线程完成之前生成未完成的记录。以下是一个可能的修复方法:

def unchunk(chunk_gen):
    """Flattens a generator of Future chunks into a generator of Future results."""
    for chunk in chunk_gen:
        old_res = None
        for f in chunk:
            res = f.result() # get result from Future
            if old_res and res is not old_res:
                yield old_res
            old_res = res
    if old_res:
        yield old_res

尝试在
rest\u api\u lookup
中迭代dict键,而不是在
thread
中。对每个键的请求都将按顺序执行,但您仍将至少并发地运行记录流,但实际上RESTAPI不能在一个调用中执行3个输入。这就是为什么我仍然需要按钥匙打电话。这就是我要说的。循环键,每个键一个接一个地调用rest。如果我有很多键,这会减慢速度(因为每个项不会并发)。在
unchunk
中以某种方式进行重复数据消除是否安全?看,如果有N个线程和K*N个块,那么线程是否按顺序处理所有键或块的任何其他项实际上并不重要。只要每个线程都很忙,你就会没事的。另一种选择是使用asyncio,但实际上,如果您真的需要它,您应该进行测量。几千个项目听起来一点也不多虽然
record
增长了,
key
似乎从来没有通过
*\u neg
(输出)键,但我还是会使用
list(record)
来确保安全。为了安全起见,我会将
len(chunk)>=
改为
=
,但是
chunk
会一个接一个地增长,所以这不是问题。@hobbes3-我在运行了你的代码后更新了我的答案,现在看起来运行正常
        if len(chunk) == threads:  # try len(chunk) >= threads
            yield chunk
            chunk = []
def unchunk(chunk_gen):
    """Flattens a generator of Future chunks into a generator of Future results."""
    for chunk in chunk_gen:
        old_res = None
        for f in chunk:
            res = f.result() # get result from Future
            if old_res and res is not old_res:
                yield old_res
            old_res = res
    if old_res:
        yield old_res