0

我編寫了一個使用python實現線程和隊列的caesar-cipher的程序。我想在代碼中改變所有的多線程工作,我不知道該怎麼做。如果你能解釋如何開始執行,我將不勝感激。這裏是代碼:如何在代碼中使用多處理來更改多線程(Python)

import threading 
import Queue 
import sys 
import string 

lock = threading.Lock() 
def do_work(in_queue, out_queue, shift): 
    while True: 
     lock.acquire() 
     item = in_queue.get() 
     result = caesar(item, shift) 
     out_queue.put(result) 
     in_queue.task_done() 
     lock.release() 
def caesar(plaintext, shift): 
    plaintext = plaintext.upper() 
    alphabet = string.ascii_uppercase 
    shifted_alphabet = alphabet[shift:] + alphabet[:shift] 
    table = string.maketrans(alphabet, shifted_alphabet) 
    return plaintext.translate(table) 

if __name__ == "__main__": 
    if len(sys.argv) != 4: 
     print("Duzgun giriniz: '<filename>.py s n l'") 
     sys.exit(0) 
    else: 
     s = int(sys.argv[1]) 
     n = int(sys.argv[2]) 
     l = int(sys.argv[3]) 

    work = Queue.Queue() 
    results = Queue.Queue() 
    myfile=open('metin.txt','r') 
    text_data=myfile.read() # <=== here load file 
    index=0 

    for i in xrange(n): 
     t = threading.Thread(target=do_work, args=(work, results, s)) 
     t.daemon = True 
     t.start() 

    for i in range(0, len(text_data), l): 
     work.put(text_data[index:index + l]) 
     index += l 

    work.join() 

    index=0 
    output_file=open("crypted"+ "_"+ str(s)+"_"+str(n)+"_"+str(l)+".txt", "w") 
    for i in range(0, len(text_data), l): 
     output_file.write(results.get()) 
     index += l 
    sys.exit() 
+0

'do_work'中的鎖定是個問題。但它不應該在那裏。 'Queue.get'已經是線程安全的,所以你沒有保護它。相反,當1個線程完成工作時,所有線程都會在該鎖上等待。你已經有效地單線程你的多線程應用程序。 – tdelaney

+0

您可以用'multiprocessing.Pool'池替換大部分代碼並使用其'map'方法。作爲一個額外的好處,'multiprocessing.pool.ThreadPool'實現一個具有相同接口的線程版本。 – tdelaney

回答

0

您可以保存自己的一些代碼並移動到標準的multiprocessing.Pool實現。

import multiprocessing 
import sys 
import string 
import itertools 

# for non-forking systems like Windows 
def worker(args): 
    # args: (text, shift) 
    return caesar(*args) 

# for forking systems like linux 
def forking_worker(args): 
    # args: ((start_index, end_index), shift) 
    return caesar(text_data[args[0][0]:args[0][1], args[1]) 

def caesar(plaintext, shift): 
    plaintext = plaintext.upper() 
    alphabet = string.ascii_uppercase 
    shifted_alphabet = alphabet[shift:] + alphabet[:shift] 
    table = string.maketrans(alphabet, shifted_alphabet) 
    return plaintext.translate(table) 

if __name__ == "__main__": 
    if len(sys.argv) != 4: 
     print("Duzgun giriniz: '<filename>.py s n l'") 
     sys.exit(0) 
    else: 
     s = int(sys.argv[1]) 
     n = int(sys.argv[2]) 
     l = int(sys.argv[3]) 

    pool = multiprocessing.Pool() # todo: change number of cpus... 
    with open('metin.txt') as myfile: 
     text_data=myfile.read() # <=== here load file 

    # on a forking system so only pass index, not text to child 
    result = pool.map(forking_worker, 
     zip(((index, index + l) 
      for index in range(0, len(text_data), l)), 
      itertools.cycle([s]))) 

    with open("crypted"+ "_"+ str(s)+"_"+str(n)+"_"+str(l)+".txt", "w") as output_file: 
     output_file.writelines(result) 
+0

非常感謝您的回答,即使我想使用fork來實現這個多處理,這似乎更好。你有沒有關於如何開始學習Pool功能的建議? –

+0

https://docs.python.org/3.6/library/multiprocessing.html上的標準文檔是一個好的開始。但是有一些小問題,所以特定方法的額外搜索是一個好主意。例如,在我給你的例子中,由於你在分岔操作系統上,所以你不需要把文本發送給孩子。我將使用索引進行更新。 – tdelaney

相關問題