python 如何实现并行查找关键字所在的行?
高洛峰
高洛峰 2017-04-17 17:45:22
0
3
1107

我有几十万个关键字放在文件4.txt中,想提取文件3.txt中含有关键字的行,保存到文件5.txt中.
文件3有200万行,我使用下面的代码可以实现我的要求,但是非常慢,一个下午还没运行完,谁有快一点的方法?
使用并行改如何改造呢?我看到这里有个并行的帖子,,与我的不同的事,我要同时读以及查询同一个文件,上述链接可以并行操作多个文件。

with open('3.txt', 'r') as f3, open('4.txt', 'r') as f4, open('result.txt', 'w') as f5:
    a = [line.strip() for line in f4.readlines()]
    for li in f3.readlines():
        new_line = li.strip().split()[1][:-2]
        for i in a:
            if i in new_line:
                f5.writelines(li)
高洛峰
高洛峰

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

membalas semua(3)
阿神

Oleh kerana tiada fail sebenar, saya tidak dapat memberi anda jaminan 100%, tetapi untuk kod anda, saya mempunyai beberapa cadangan untuk peningkatan kecekapan:

(Mungkin anda akan mendapati bahawa kod yang dipertingkatkan tidak memerlukan penyelesaian selari sama sekali)


Pertama sekali, masalah besar ialah readlines() Kaedah ini akan membaca semua baris dalam objek fail sekali gus Ini jelas sangat lemah untuk kecekapan dan penggunaan sumber baris. Saya perlu membaca semuanya dalam satu sesi, yang sangat menakutkan.

Untuk analisis dan perbincangan terperinci, sila rujuk Jangan sekali-kali memanggil readlines() pada fail

(Perenggan dalam artikel ini hampir boleh dianggap sebagai amaran)

Terdapat beratus-ratus soalan di tempat seperti StackOverflow tentang kaedah readlines, dan dalam setiap kes, jawapannya adalah sama.
"Kod saya mengambil masa lama sebelum ia bermula, tetapi ia agak pantas sebaik sahaja ia berjalan."
Itu kerana anda memanggil talian baca.
"Kod saya nampaknya lebih teruk daripada linear pada saiz input, walaupun ia hanya gelung mudah. "
Itu kerana anda memanggil talian baca.
"Kod saya tidak dapat mengendalikan fail gergasi kerana ia kehabisan memori."
Itu kerana anda sedang memanggil talian baca.

Kesimpulannya ialah: Adalah disyorkan bahawa semua tempat di mana readlines digunakan hendaklah ditukar kepada .

Contoh:

with open('XXX', 'r') as f:
    for line in f.readlines():
       # do something...

mesti ditukar kepada:

with open('XXX', 'r') as f:
    for line in f:
       # do something...

Secara intuitif, kecekapan akan menjadi lebih baik.


Kedua, anda menggunakan senarai untuk mencari kata kunci, yang juga agak tidak cekap:

for i in a:
    if i in new_line:

Untuk mengesahkan sama ada terdapat kata kunci new_line dalam i, kami melawati keseluruhan senarai kata kunci: a, yang mungkin baik untuk situasi umum, tetapi untuk ratusan ribu perbandingan kata kunci, ia adalah Melawat setiap baris a akan menyebabkan banyak pembaziran masa Katakan terdapat x kata kunci dalam a, y baris dalam f3 dan z perkataan dalam setiap baris Masa yang dihabiskan di sini ialah x*y*z(Bergantung pada bilangan baris dalam fail anda, susunan magnitud ini sangat mengejutkan).

Sudah tentu adalah lebih baik untuk hanya menggunakan beberapa bekas yang menggunakan cincang untuk mencari, seperti dictionary atau set.


Bahagian terakhir ialah tentang carian anda:

for li in f3.readlines():
    new_line = li.strip().split()[1][:-2]
    for i in a:
        if i in new_line:
            f5.writelines(li)

Saya tidak begitu memahami perkara ini, new_line nampaknya subrentetan, dan kini anda mahu menggunakan rentetan ini untuk membandingkan kata kunci?

Tetapi mengetepikan perkara ini, mengenai new_line yang mengandungi kata kunci, nampaknya selepas mencetak, ia tidak sepatutnya terus bergelung a, melainkan anda maksudkan terdapat beberapa kata kunci dalam new_line yang ingin saya cetak line Beberapa kali. Jika tidak, menambah break juga boleh mempercepatkan proses.


Adalah disyorkan bahawa kod anda ditukar kepada:

with open('3.txt') as f3, open('4.txt') as f4, open('result.txt', 'w') as f5:
    keywords = set(line.strip() for line in f4)
    for line in f3:
        new_line = line.strip().split()[1][:-2]
        for word in new_line:
            if word in keywords:
                print(line, file=f5)
                break

Jika saya salah faham, sila beritahu saya dan mari kita bincangkan semula secara intuitif, masalah anda boleh diselesaikan tanpa menggunakan selari

伊谢尔伦

automaton ac

黄舟

Berdasarkan jawapan @dokelung, dengan sedikit pengubahsuaian, ia pada asasnya boleh memenuhi keperluan saya. Jawapan ini agak berbeza daripada menggunakan grep -f 4.txt 3.txt &gt 5.txt;

with open('3.txt') as f3, open('4.txt') as f4, open('result.txt', 'w') as f5:
    keywords = set(line.strip() for line in f4)
    for line in f3:
        new_line = line.strip().split()[1][:-2]
        if new_line in keywords:
            print(line.strip(), file=f5)
            
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan