0

파이썬과 함께 스레드 및 대기열을 사용하여 시저 암호를 구현하는 프로그램을 작성했습니다. 내 코드에서 다중 처리를 사용하여 모든 스레딩 작업을 변경하고 싶습니다. 어떻게 처리해야할지 모르겠습니다. & 구현을 시작하는 방법을 설명 할 수 있다면 감사하겠습니다.코드 (파이썬)에서 멀티 프로세싱으로 멀티 스레딩을 변경하는 방법

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'는 이미 스레드로부터 안전하기 때문에 여러분은 그것을 보호하지 않습니다. 대신 모든 스레드가 해당 잠금을 기다리는 동안 한 스레드는 작업을 수행합니다. 멀티 스레드 응용 프로그램을 효율적으로 싱글 스레드했습니다. – 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

이 다중 처리를 구현하기 위해 포크를 사용하고 싶지만이 답변을 주셔서 대단히 감사합니다. 풀 기능 학습을 시작하는 방법에 대한 제안이 있습니까? –

+0

https://docs.python.org/3.6/library/multiprocessing.html의 표준 문서는 좋은 시작입니다. 그러나 도처에 따라 가면서 특정 방법을 추가로 검색하는 것이 좋습니다. 예를 들어, 당신이 준 운영 체제에 있기 때문에 내가 준 예제에서 텍스트를 자식에게 보낼 필요가 없습니다. 대신 인덱스를 사용하여 업데이트하겠습니다. – tdelaney

관련 문제