我具有以下功能:
def update_contacts(data):
'''
Update a user's contacts from Google: to be run as a background task.
'''
from users.google_oauth import GoogleOauthClient
email = data['email']
access_token = data['access_token']
g = GoogleOauthClient()
contacts = g.get_all_contacts(email=email, access_token=access_token, insert=True)
log.info('Fetched and updated %s contacts' % (len(contacts)))
我正在寻找创建一个通用函数,该函数将在后台运行其他函数,例如上面的函数。这是我到目前为止的内容:
def run_in_background(function):
'''
I want this to be able to receive a normal function call,
such as `update_contacts(data)` or get_first_name('tom')
'''
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_in_executor(None, function, data)
然后我会将此传递称为:
data={'email': email,'access_token': g.tokens['access_token']}
run_in_background (
update_contacts(data)
)
问题是,我认为它将首先运行update_contacts
函数,并且实际上不会做任何异步操作。我如何正确编写和调用run_in_background
函数?
也许我需要使用类似partial
之类的方法来传递函数,而无需实际调用它,直到函数执行为止?
答案 0 :(得分:3)
正如其他指出的那样,表达式run_in_background(update_contacts(data))
在调用update_contacts(data)
之前将对run_in_background
求值。无论如何实现run_in_background
,都必须向其传递 function 。
您要查找的run_in_background
函数已经存在,它是ThreadPoolExecutor
上的submit
方法:
with ThreadPoolExecutor() as executor:
data = { ... }
future = executor.submit(update_contacts, data)
# ... the function now runs in a background thread,
# and you can do other things here ...
您可以对返回的Future
对象使用诸如done()
或result()
之类的方法来测试提交的任务是否已完成或获取函数的结果。这比手动启动线程更可取,因为执行器可以通过维护线程池来支持大量后台任务。还有一个执行器使用multiprocessing提供真正的并行性。
所有这些都完全独立于asyncio库及其run_in_executor
方法,该方法用于将阻塞代码与专门为asyncio编写的代码(您似乎没有)连接起来。
答案 1 :(得分:0)
不确定asyncio。但是,我相信您也可以使用线程, 然后可以如下修改您的函数:
def background_function(func, params):
t1 = threading.Thread(target=func, args = params)
t1.start()
通话示例:
def do_something(num):
print('printing' + num + 'times')
def call_do_domething():
background_function(do_something, args = [1000])
答案 2 :(得分:-1)
如果您调用run_in_background (update_contacts(data))
,则意味着您已经调用了函数update_contacts(data)
。但是,您只应像这样传递函数及其参数:
run_in_background(update_contacts, args=(data,))
然后相应地更改您的run_in_background
函数
def run_in_background(function, args=()):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_in_executor(None, function, *args)