多线程 - 为何python子线程会等待很长时间
高洛峰
高洛峰 2017-04-18 09:32:14
0
2
668

背景:运行一个爬虫,开了10个线程,每个线程先去爬取指定数量的代理作为自己的代理池,然后开始工作。

问题:下面是爬虫日志的两行,可以看到在第一行任务处等待了45秒,而这里不过是输出一条信息,十分不理解为什么等了这么长时间?日志中像这样动辄十几秒什么一两分钟的情形基本都发生在爬取代理的过程中,是否意味着这个任务的代码有问题?

15:57:50    INFO    Thread-2    the proxy already in list, skip
15:58:35    INFO    Thread-10       {'https': '117.170.28.178:8123'} download 2111 bytes in 0.75 seconds(average in 1 tries), need 10, available count: 7    

思考:我理解python的多线程调度机制是完成了一条指令后,就可以调用其他线程了,并不是一定要等着这个指令得到了预期的结果,那么如果我的代码写的有问题也不至于影响他的调度吧。这个线程没有进展又不将CPU的使用权让渡出来,GIL为什么不剥夺这个线程的运行时间,总不至于是在等待某个程序块或者函数运行完毕吧。

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

membalas semua(2)
小葫芦

Didapati masalah yang diterangkan terutamanya disebabkan oleh penggunaan SQLite yang tidak betul Reka bentuk sebelumnya adalah untuk membuka sambungan sehingga pengesahan semua ejen dalam kumpulan ejen selesai dan sejumlah ejen ditangkap sebelum menutupnya. sambungan, dan setiap kali Apabila menambah, mengubah suai atau memadam maklumat ejen, fail data ditulis, yang menyebabkan SQLite berbutir kasar dikunci untuk masa yang lama.

Selepas menemui masalah ini, kami mengoptimumkannya Selepas membaca ejen inventori pada permulaan sambungan baharu, kami segera menutup sambungan Selepas itu, semua data ejen baharu, dikemas kini dan dipadamkan disimpan sementara dalam pembolehubah kelas sehingga semua ejen yang diperlukan diperolehi Kemudian, buka sambungan baru, kemas kini data dengan executemany, kemudian tutup sambungan, selesaikan tugas yang dijadualkan, dan kelajuan akan meningkat.

Walau bagaimanapun, saya masih tidak faham mengapa dalam situasi asal, mekanisme penjadualan utas membenarkan utas yang disekat oleh pangkalan data sentiasa menduduki sumber dan bukannya menukar masa?

伊谢尔伦

Jadi urutan anda disekat pada tahap menulis ke pangkalan data Memandangkan anda menggunakan sqlite, izinkan saya memberi anda satu lagi kuasa purba untuk mempercepatkan operasi penulisan pangkalan data:

.
import sqlite3

...
conn = sqlite3.connect('xxx.db')
cur = conn.cursor()
cur.execute("CREATE TABLE xxx")  # 建个表
cur.execute("PRAGMA synchronous = OFF")  # 关闭磁盘同步
cur.execute("BEGIN TRANSACTION")  # 开始事务处理
cur.executemany("INSERT INTO names VALUES (?,?)", lst)  # 批量插入爬到的数据
conn.commit()
conn.close()
...

Tiga kaedah digunakan untuk mempercepatkan sqlite kelajuan menulis

  1. Matikan penyegerakan cakera

  2. Transaksi SQLite

  3. laksanakan banyak sisipan kelompok

PS: Di samping itu, jika anda mempunyai memori yang mencukupi, anda boleh membuang fail pangkalan data ke dalam direktori tmpfs, yang akan menghapuskan kesan I/O cakera (bersamaan dengan menulis terus dalam ingatan)

.
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!