设计
首先,在增加复杂性之前(特别是涉及并发编程),您应该问自己,我真的需要这样做吗?Flask应用程序是否可以在请求时触发新的抓取?
并发性
在Python中需要同时运行任务时,有三种主要方法:
多线程
多进程
asyncio
进程在操作系统方面是不同的东西,并包含线程。asyncio
是另一种思考这个问题的方式,它允许您忘记操作系统。
Python有一个名为
全局解释器锁的特性,这基本上意味着它一次只能在一个进程中解释一行字节码。这意味着如果您的应用程序使用
多线程
,则一个线程将冻结,而另一个线程将执行其他任务。需要注意的是,此限制仅适用于解释字节码,如果有像
flask
服务器这样的IO密集型工作,那么当服务器忙于处理任务时,您可能会发现仍有足够的时间可以使用
多线程
。
为什么要选择多进程
?
很多工作已经投入到使
多线程
和
多进程
之间的接口非常相似,因此它增加了非常少的复杂性,并且为了确保您不会阻塞您的服务器,最好只使用
多进程
。
为什么要选择多线程
?
multiprocessing
的缺点在于 Python 必须在进程之间pickle数据,因为它们不能像线程一样共享内存。与 multithreading
相比,这种方法较慢,但对于合理数量的数据仍然非常快。记住,“过早优化是万恶之源”,在进行优化之前和之后profile你的代码,以决定是否值得。
为什么选择 asyncio
asyncio
是为了“使编写显式异步、并发的Python代码更加容易和Pythonic”而添加到Python中的,有些人可能不同意。我认为最好尝试一下,看看它是否适合您的需求。从您的应用程序声音来看,它不够大,无法从asyncio
允许的大规模并发中受益。
个人而言,我会选择multiprocessing
来处理这种情况。
导入
通常不希望import my_script_which_loops
永远挂起,而是经常会看到以下内容:
def main():
while True:
print("I am scraping the thing!")
if __name__ == "__main__":
main()
这意味着如果您运行
\> python my_script_which_loops.py
,则会按预期方式抓取内容,但是如果该脚本不是主要脚本,则导入它不会挂起。有关更多信息,请参见
此处。
multiprocessing
。 - Peter Wood