Python 线程随机返回错误结果

标签 python multithreading rest python-multithreading

我的问题

我一直在使用Python库Thread,它在返回正确结果方面似乎存在一些问题。当我运行相同的功能时,例如连续十次,八次结果正确,两次错误。

当结果错误时,这是​​因为来自各个调用的一些结果字典似乎被随机合并在一起。

我的代码:

此函数创建一个 session ,重试某些状态代码的其余调用:

# Makes retry sessions
def requests_retry_session(retries=3,backoff_factor=0.3,status_forcelist=(500, 502, 504),session=None):
    """
    Description:
        Creates a session which uses retries
    Input:
        retries (int):  Max number of retries
        backoff_factor (int): Time between retries
        status_forcelist (tuble): Status for which to retry
    Returns:
        session: Requests session which handles different status and connection errors
    """
    session = session or requests.Session()
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        redirect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
    )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session

此函数对多个 url 进行剩余调用:

def make_rest_calls(urls, header, store=None):
    """
    Description:
        Processes list of urls
    Input:
        urls (list): List of urls for rest call
        header (dictionary): Dictionary containing credentials
        store (dictionary): Dictionary for collecting results
    Returns:
        store (dictionary): Dictionary with results
    """
    if store is None:
        store = {}
    for url in urls:
        store[url] = requests_retry_session().get(url, headers=header, timeout=5)

    return store

该函数以多线程方式运行剩余调用

def run_multi_threaded(nthreads, list_of_urls, header):
    """
    Description:
        Runs multiple threads
    Input:
        nthreads (int): Number for threads to run
        list_of_urls(list): List of rest urls
        header (dictionary): Dictionary containing credentials
    Returns:
        store (dictionary): Dictionary with results
    """
    store = {}
    threads = []

    # create the threads
    for i in range(nthreads):
        small_list_of_urls = list_of_urls[i::nthreads]
        t = Thread(target=make_rest_calls, args=(small_list_of_urls))
        threads.append(t)

    # start the threads
    [t.start() for t in threads ]
    # wait for the threads to finish
    [ t.join() for t in threads ]

    return store

问题

这是该软件包的弱点吗?我应该使用多个进程吗?或者我做错了什么,只在某些时候导致这种副作用?

我需要进行很多调用,因此需要多线程完成。显然也必须是正确的。

最佳答案

正如 blhsing 提到的,这个问题可能没有显示一些有助于回答它的细节。

根据结果的描述(随机合并输出,仅在某些情况下),似乎在以下情况下可能会发生并发问题:

  1. 确实将 store 作为参数传递给线程启动中的 make_rest_calls 函数。 (如果 make_rest_calls 中 store 的默认值确实是“{}”而不是 None,也可能会发生这种情况)
  2. list_of_urls 中几乎没有重复项。

如果这两种情况以某种方式发生,结果可能如所描述的那样,因为两个不同的线程可能会尝试同时更改同一存储条目。

如果是这种情况,简单的解决方案可能是确保您的 list_of_urls 不会两次保存相同的 URL。 (例如,您可能想使用 set(list_of_urls)。)

值得一提的是,至少在这种用法中,make_rest_calls 函数中没有返回任何内容,因为线程不返回函数的返回值。例如,唯一可行的方法是改变输入存储值,而不是返回任何内容。

关于Python 线程随机返回错误结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56579256/

相关文章:

json - API 库中的后台获取

rest - 1C中如何通过OData获取额外的props?

python - 初学者对python中的类和方法的询问

python - Windows - 无法通过 pip 安装 pyautogui - 错误 : Command "python setup.py egg_info" failed with error code 1

c# - 线程FTP上传C#

java - MultipartEntityBuilder 将 Content-Disposition header 添加到二进制文件并破坏它

python - 为什么我的 OpenGL 程序无法加载 GLUT 位图字体?

python - 对数 y 轴使刻度标签消失

c++ - 线程opencl编译

ruby-on-rails - ActionMailer::Base.default_url_options线程安全吗?