与锁定的异步无效

发布于 2025-01-31 08:53:11 字数 2097 浏览 3 评论 0原文

我有一个异步方法,如下所示。

我传递了1000个数字的列表,其中该方法将在每个数字中传递给辅助功能,从而将某些内容从网站返回。

我有一个名为Count的全局变量,我将其包围起来,以确保它不会通过

我使用add_done_callback的任何其他内容而更改它,以使此方法async。

目的是继续向服务器发送1000个数字列表中的数字,并且只有服务器返回数据(可以花费0.1至2秒的时间),暂停,将数据写入SQL数据库,然后继续继续

该代码无需锁定,也可以按预期工作,也没有使回调函数(下面命名为“函数”)异​​步。但是添加锁会给我一个错误:Runtime Warning:Coroutine'函数'从未等待self._context.run(self._callback, *self._args)Runtime Warning:Enable tracemalloc使对象分配追溯

i。在Python中,As Super New to Async,因此所有的帮助/建议都非常适合

我的代码。这只是一个简单的草稿:

import time
import random
import asyncio
# from helper import get_message_from_server

async def get(number):
    # get_message_from_server(number), which takes somewhere between 0.1 to 2 seconds
    await asyncio.sleep(random.uniform(0.1, 2)) 
    s = 'Done with number ' + number
    return s

async def function(future, lock):
    global count
    print(future.result())
    # write future.result() to db
    acquired = await lock.acquire()
    count -= 1 if (count > 1) else 0
    lock.release()

async def main(numbers, lock):
    global count 
    
    count = 0
    
    for i, number in enumerate(numbers):
        print('number:', number, 'count:', count)
        acquired = await lock.acquire()
        count += 1
        lock.release()
        task = asyncio.create_task(get(number))
        
        task.add_done_callback(
            lambda x: function(x, lock)
        )
        if (count == 50):
            print('Reached 50')
            await task

            acquired = await lock.acquire()
            count = 0
            lock.release()

        if (i == len(numbers) - 1):
            await task

def make_numbers():
    count = []
    for i in range(1001):
        count.append(str(i))
    return count

if __name__ == '__main__':
    numbers = make_numbers()
    loop = asyncio.get_event_loop()
    lock = asyncio.Lock()
    try:
        loop.run_until_complete(main(numbers, lock))
    except Exception as e:
        pass
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.stop()

I have an async method, as shown below.

I pass in lists of 1000 numbers, where the method will pass in each number to a helper function which will return something from a website.

I have a global variable called count, which i surround with locks to make sure it doesnt get changed by anything else

I use add_done_callback with the task to make this method async.

The goal is to keep sending a number in the list of 1000 numbers to the server, and only when the server returns data (can take anywhere from 0.1 to 2 seconds), to pause, write the data to a sql database, and then continue

The code works as expected without locks, or without making the callback function, (which is named 'function' below) asyncrounous. But adding locks gives me an error: RuntimeWarning: coroutine 'function' was never awaited self._context.run(self._callback, *self._args) RuntimeWarning: Enable tracemalloc to get the object allocation traceback

I am super new to async in python so any help/advice is greatly appriciated

My code is shown below. It is just a simple draft:

import time
import random
import asyncio
# from helper import get_message_from_server

async def get(number):
    # get_message_from_server(number), which takes somewhere between 0.1 to 2 seconds
    await asyncio.sleep(random.uniform(0.1, 2)) 
    s = 'Done with number ' + number
    return s

async def function(future, lock):
    global count
    print(future.result())
    # write future.result() to db
    acquired = await lock.acquire()
    count -= 1 if (count > 1) else 0
    lock.release()

async def main(numbers, lock):
    global count 
    
    count = 0
    
    for i, number in enumerate(numbers):
        print('number:', number, 'count:', count)
        acquired = await lock.acquire()
        count += 1
        lock.release()
        task = asyncio.create_task(get(number))
        
        task.add_done_callback(
            lambda x: function(x, lock)
        )
        if (count == 50):
            print('Reached 50')
            await task

            acquired = await lock.acquire()
            count = 0
            lock.release()

        if (i == len(numbers) - 1):
            await task

def make_numbers():
    count = []
    for i in range(1001):
        count.append(str(i))
    return count

if __name__ == '__main__':
    numbers = make_numbers()
    loop = asyncio.get_event_loop()
    lock = asyncio.Lock()
    try:
        loop.run_until_complete(main(numbers, lock))
    except Exception as e:
        pass
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.stop()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼眸里的那抹悲凉 2025-02-07 08:53:11

上面的评论对此有所帮助,

这是最终工作代码的样子:

import time
import random
import asyncio
from functools import partial
# from helper import get_message_from_server

async def get(number):
    # get_message_from_server(number), which takes somewhere between 0.1 to 2 seconds
    await asyncio.sleep(random.uniform(0.1, 2)) 
    s = 'Done with number ' + number
    return s

def function(result, lock):
    
    print(result.result())

    async def count_decrement(lock):
        global count
        print('in count decrement')
        acquired = await lock.acquire()
        count -= 1 if (count > 1) else 0
        lock.release()

    asyncio.create_task(count_decrement(lock))

async def main(numbers, lock):
    global count 
    count = 0
    for i, number in enumerate(numbers):
        print('number:', number, 'count:', count)
        acquired = await lock.acquire()
        count += 1
        lock.release()
        task = asyncio.create_task(get(number))
        
        task.add_done_callback(partial(function, lock = lock))

        if (count == 50):
            print('Reached 50')
            await task

            acquired = await lock.acquire()
            count = 0
            lock.release()

        if (i == len(numbers) - 1):
            await task

def make_numbers():
    count = []
    for i in range(1001):
        count.append(str(i))
    return count

if __name__ == '__main__':
    numbers = make_numbers()
    loop = asyncio.get_event_loop()
    lock = asyncio.Lock()
    try:
        loop.run_until_complete(main(numbers, lock))
    except Exception as e:
        pass
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.stop()

The above comment helped a lot

This is what the final working code looks like:

import time
import random
import asyncio
from functools import partial
# from helper import get_message_from_server

async def get(number):
    # get_message_from_server(number), which takes somewhere between 0.1 to 2 seconds
    await asyncio.sleep(random.uniform(0.1, 2)) 
    s = 'Done with number ' + number
    return s

def function(result, lock):
    
    print(result.result())

    async def count_decrement(lock):
        global count
        print('in count decrement')
        acquired = await lock.acquire()
        count -= 1 if (count > 1) else 0
        lock.release()

    asyncio.create_task(count_decrement(lock))

async def main(numbers, lock):
    global count 
    count = 0
    for i, number in enumerate(numbers):
        print('number:', number, 'count:', count)
        acquired = await lock.acquire()
        count += 1
        lock.release()
        task = asyncio.create_task(get(number))
        
        task.add_done_callback(partial(function, lock = lock))

        if (count == 50):
            print('Reached 50')
            await task

            acquired = await lock.acquire()
            count = 0
            lock.release()

        if (i == len(numbers) - 1):
            await task

def make_numbers():
    count = []
    for i in range(1001):
        count.append(str(i))
    return count

if __name__ == '__main__':
    numbers = make_numbers()
    loop = asyncio.get_event_loop()
    lock = asyncio.Lock()
    try:
        loop.run_until_complete(main(numbers, lock))
    except Exception as e:
        pass
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.stop()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文