python - 如何执行函数列表并将数据传递给使用 asyncio 调用的适当函数
问题描述
我以前使用请求,但后来我转移到 aiohttp + asyncio 以并行运行帐户,但是我无法将逻辑放在我的脑海中。
class Faked(object):
def __init__(self):
self.database = sqlite3.connect('credentials.db')
async def query_login(self, email):
print(email)
cur = self.database.cursor()
sql_q = """SELECT * from user WHERE email='{0}'""".format(email)
users = cur.execute(sql_q)
row = users.fetchone()
if row is None:
raise errors.ToineyError('No user was found with email: ' + email + ' in database!')
self.logger().debug("Logging into account '{0}'!".format(row[0]))
call_func = await self._api.login(data={'email': row[0],
'password': row[1],
'deviceId': row[2],
'aaid': row[3]})
return await call_func
async def send_friend_request(self, uid):
return await self._api.send_friend_request(uid)
def main(funcs, data=None):
"""
todo: fill
:rtype: object
"""
tasks = []
if isinstance(funcs, list):
for func in funcs:
tasks.append(func)
else:
tasks.append(funcs)
print(tasks)
loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*tasks))
for result in results:
print(result)
return results
if __name__ == '__main__': # for testing purposes mostly
emails = ['email@hotmail.com', 'email@outlook.com', 'email@gmail.com']
我基本上只是想知道如何对多个函数进行排队,在本例中为 query_login 和 send_friend_request,同时还将正确的数据传递给所述函数,假设我同时在一个社交媒体应用程序上运行三个帐户,这真的让我大吃一惊,虽然我有使事情过于复杂的倾向,但任何帮助将不胜感激。
解决方案
Python 旨在通过解包运算符 * 或使用 lambda 使这变得相当容易。这个线程中有几个很好的答案,它们有你需要的东西:
让我们来看看它。
callstack = [] # initialize a list to serve as our stack.
# See also collections.deque for a queue.
然后我们可以定义我们的函数:
def somefunc(a, b, c):
do stuff...
然后使用参数作为列表添加对堆栈的调用。
args = [a, b, c]
callstack.append((somefunc, args)) # append a tuple with the function
# and its arguments list.
# calls the next item in the callstack
def call_next(callstack):
func, args = callstack.pop() # unpack our tuple
func(*args) # calls the func with the args unpacked
* 运算符解包您的列表并按顺序将它们作为参数提供。您还可以使用双星运算符 (**) 解压缩关键字参数。
def call_next(callstack):
func, args, kwargs = callstack.pop() # unpack our tuple
func(*args, **kwargs) # calls the func with both args and kwargs unpacked.
另一种方法是只制作一个 lambda。
def add(a, b):
return a + b
callstack = []
callstack.append(lambda: add(1, 2))
callstack.pop()() # pops the lambda function, then calls the lambda function,
# which just calls the function as you specified it.
瞧!所有归功于其他线程中的作者。这里有一个陷阱:如果您将对象作为参数传递,它将作为引用传递。请小心,因为您可以在对象被堆栈调用之前对其进行修改。
def add(a, b, c):
return a + b + c
badlist = [1,2,3]
callstack.append((somefunc, badlist))
badlist = [2, 4, 6]
callstack.append((somefunc, badlist))
while len(callstack) > 0:
print(call_next(callstack))
# Prints:
12
12
你可以在 *args 版本中解决这个问题:
# make a shallow copy and pass that to the stack instead.
callstack.append((somefunc, list(badlist)))
在 lambda 函数中,整个事物都是在调用时评估的,因此即使通常不是引用的事物也会表现得像引用。上述技巧不起作用,因此在创建 lambda 之前根据需要进行任何复制。
推荐阅读
- python - 如何更改已打开流的缓冲?
- python - 带有 Agg 最小/最大日期的 Pandas Groupby
- php - 流明框架中的POST请求不允许异常
- javascript - Javascript - 当输入中有内容时按钮可见
- azure - 是否需要将 Azure IP 数据中心 IP 添加到应用服务白名单?
- android - Android Studio:使用模拟器退出代码 2?
- javascript - 通过使用 Javascript 匹配元素将两个数组合二为一
- javascript - 如何使用多个值更新反应状态并使用回调函数依赖于更新的状态。它会起作用吗?
- google-cloud-platform - 谷歌云平台上的 HDP
- ios - 检测 SKSpriteNodes 上的触摸事件