Python 通过网络IO和数据库查询改进多线程处理
我正在写一个脚本:Python 通过网络IO和数据库查询改进多线程处理,python,multithreading,multiprocessing,mysql-python,pycurl,Python,Multithreading,Multiprocessing,Mysql Python,Pycurl,我正在写一个脚本: 从数据库中获取URL列表(约10000个URL) 下载所有页面并将其插入数据库 解析代码 如果(某些条件)在数据库中进行其他插入 我有一个带超线程的Xeon四核,所以总共有8个线程可用,我在Linux(64位)下 我使用cStringIO作为缓冲区,pycurl获取页面,BeautifulSoup解析页面,MySQLdb与数据库交互 我试图简化下面的代码(删除所有try/except、解析操作等) 我使用了多线程处理,因此,如果某些请求因超时而失败,我不需要等待。该特定线程将
cStringIO
作为缓冲区,pycurl
获取页面,BeautifulSoup
解析页面,MySQLdb
与数据库交互
我试图简化下面的代码(删除所有try/except、解析操作等)
我使用了多线程处理
,因此,如果某些请求因超时而失败,我不需要等待。该特定线程将等待,但其他线程可以继续使用其他URL
除了脚本什么也不做的屏幕截图。似乎有5个内核正忙,而另一个则不忙。因此,问题是:
- 我应该创建与线程数量相同的游标吗
- 我真的需要锁定查询的执行吗?如果一个线程执行cur.execute()而不是db.commit(),而另一个线程执行另一个查询并提交,会发生什么情况
- 我读过关于这个类的文章,但我不确定我是否理解正确:我可以用它来代替锁定+提取url+释放吗
- 使用
是否会遇到I/O(网络)瓶颈?使用100个线程,我的速度不会超过~500Kb/s,而我的连接速度会更快。如果我转到多线程
,我会看到这方面的一些改进吗多进程
- 同样的问题,但MySQL:使用我的代码,这方面可能会有瓶颈?所有这些锁+插入查询+释放都可以通过某种方式改进吗
- 如果方法是多线程,那么100是大量线程吗?我的意思是,太多执行I/O请求(或DB查询)的线程是无用的,因为这些操作相互排斥?或者更多线程意味着更高的网络速度
threading.Thread
替换为multiprocessing.Process
来测试它。关于@COpython我已经试过了,CPU和网络使用率似乎都在增加,但脚本正在循环,所以我不知道性能更好的原因。
import cStringIO, threading, MySQLdb.cursors, pycurl
NUM_THREADS = 100
lock_list = threading.Lock()
lock_query = threading.Lock()
db = MySQLdb.connect(host = "...", user = "...", passwd = "...", db = "...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()
cur.execute("SELECT...")
rows = cur.fetchall()
rows = [x for x in rows] # convert to a list so it's editable
class MyThread(threading.Thread):
def run(self):
""" initialize a StringIO object and a pycurl object """
while True:
lock_list.acquire() # acquire the lock to extract a url
if not rows: # list is empty, no more url to process
lock_list.release()
break
row = rows.pop()
lock_list.release()
""" download the page with pycurl and do some check """
""" WARNING: possible bottleneck if all the pycurl
connections are waiting for the timeout """
lock_query.acquire()
cur.execute("INSERT INTO ...") # insert the full page into the database
db.commit()
lock_query.release()
"""do some parse with BeautifulSoup using the StringIO object"""
if something is not None:
lock_query.acquire()
cur.execute("INSERT INTO ...") # insert the result of parsing into the database
db.commit()
lock_query.release()
# create and start all the threads
threads = []
for i in range(NUM_THREADS):
t = MyThread()
t.start()
threads.append(t)
# wait for threads to finish
for t in threads:
t.join()