RuntimeError บน windows ที่พยายามประมวลผลหลาย python


124

ฉันกำลังลองใช้โปรแกรม python อย่างเป็นทางการตัวแรกโดยใช้ Threading และ Multiprocessing บนเครื่อง windows ฉันไม่สามารถเปิดใช้งานกระบวนการได้โดย python ให้ข้อความต่อไปนี้ สิ่งนี้คือฉันไม่ได้เปิดเธรดของฉันในโมดูลหลัก เธรดได้รับการจัดการในโมดูลแยกต่างหากภายในคลาส

แก้ไข : โดยวิธีการที่รหัสนี้ทำงานได้ดีบน Ubuntu ไม่ค่อยมีบน windows

RuntimeError: 
            Attempt to start a new process before the current process
            has finished its bootstrapping phase.
            This probably means that you are on Windows and you have
            forgotten to use the proper idiom in the main module:
                if __name__ == '__main__':
                    freeze_support()
                    ...
            The "freeze_support()" line can be omitted if the program
            is not going to be frozen to produce a Windows executable.

รหัสเดิมของฉันค่อนข้างยาว แต่ฉันสามารถสร้างข้อผิดพลาดในโค้ดเวอร์ชันย่อได้ แบ่งออกเป็นสองไฟล์ไฟล์แรกเป็นโมดูลหลักและทำน้อยมากนอกเหนือจากการนำเข้าโมดูลที่จัดการกระบวนการ / เธรดและเรียกใช้เมธอด โมดูลที่สองคือส่วนที่เป็นเนื้อของรหัส


testMain.py:

import parallelTestModule

extractor = parallelTestModule.ParallelExtractor()
extractor.runInParallel(numProcesses=2, numThreads=4)

ParallelTestModule.py:

import multiprocessing
from multiprocessing import Process
import threading

class ThreadRunner(threading.Thread):
    """ This class represents a single instance of a running thread"""
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name
    def run(self):
        print self.name,'\n'

class ProcessRunner:
    """ This class represents a single instance of a running process """
    def runp(self, pid, numThreads):
        mythreads = []
        for tid in range(numThreads):
            name = "Proc-"+str(pid)+"-Thread-"+str(tid)
            th = ThreadRunner(name)
            mythreads.append(th) 
        for i in mythreads:
            i.start()
        for i in mythreads:
            i.join()

class ParallelExtractor:    
    def runInParallel(self, numProcesses, numThreads):
        myprocs = []
        prunner = ProcessRunner()
        for pid in range(numProcesses):
            pr = Process(target=prunner.runp, args=(pid, numThreads)) 
            myprocs.append(pr) 
#        if __name__ == 'parallelTestModule':    #This didnt work
#        if __name__ == '__main__':              #This obviously doesnt work
#        multiprocessing.freeze_support()        #added after seeing error to no avail
        for i in myprocs:
            i.start()

        for i in myprocs:
            i.join()

@doctorlove ฉันเรียกใช้เป็น python testMain.py
NG Algo

1
ได้สิคุณต้องมี if name == ' main ' ดูคำตอบและเอกสาร
doctorlove

1
@NGAlgo สคริปต์ของคุณมีประโยชน์กับฉันมากในขณะที่ฉันกำลังแก้ไขปัญหาเกี่ยวกับ pymongo และการประมวลผลหลายขั้นตอน ขอบคุณ!
Clay

คำตอบ:


176

ใน Windows กระบวนการย่อยจะนำเข้า (เช่นดำเนินการ) โมดูลหลักเมื่อเริ่มต้น คุณต้องใส่ตัวif __name__ == '__main__':ป้องกันในโมดูลหลักเพื่อหลีกเลี่ยงการสร้างกระบวนการย่อยซ้ำ ๆ

แก้ไขtestMain.py:

import parallelTestModule

if __name__ == '__main__':    
    extractor = parallelTestModule.ParallelExtractor()
    extractor.runInParallel(numProcesses=2, numThreads=4)

3
(เอาฝ่ามือฟาดหน้าผาก) ดู๊! มันได้ผล!!!! ขอบคุณมาก! ฉันพลาดความจริงที่ว่ามันเป็นโมดูลหลักดั้งเดิมที่นำเข้ามาใหม่! ตลอดเวลานี้ฉันพยายามตรวจสอบ" name ==" ก่อนที่ฉันจะเริ่มกระบวนการของฉัน
NG Algo

1
ดูเหมือนว่าจะไม่สามารถนำเข้า 'parallelTestModule' ได้ ฉันใช้ Python 2.7 ควรใช้งานนอกกรอบหรือไม่?
จอนนี่

2
@Jonny รหัสสำหรับ parallelTestModule.py เป็นส่วนหนึ่งของคำถาม
Janne Karila

1
@DeshDeepSingh ข้อมูลโค้ดไม่ใช่ตัวอย่างแบบสแตนด์อะโลน เป็นการแก้ไขรหัสของ OP
Janne Karila

1
@DeshDeepSingh โมดูลนั้นเป็นส่วนหนึ่งของคำถาม
Janne Karila

25

ลองใส่รหัสของคุณในฟังก์ชันหลักใน testMain.py

import parallelTestModule

if __name__ ==  '__main__':
  extractor = parallelTestModule.ParallelExtractor()
  extractor.runInParallel(numProcesses=2, numThreads=4)

ดูเอกสาร :

"For an explanation of why (on Windows) the if __name__ == '__main__' 
part is necessary, see Programming guidelines."

ซึ่งพูด

"ตรวจสอบให้แน่ใจว่าสามารถนำเข้าโมดูลหลักได้อย่างปลอดภัยโดยล่าม Python ใหม่โดยไม่ก่อให้เกิดผลข้างเคียงที่ไม่ได้ตั้งใจ (เช่นการเริ่มต้นกระบวนการใหม่)"

... โดยใช้ if __name__ == '__main__'


9

แม้ว่าคำตอบก่อนหน้านี้จะถูกต้อง แต่ก็มีภาวะแทรกซ้อนเล็กน้อยที่จะช่วยให้สังเกตได้

ในกรณีที่โมดูลหลักของคุณอิมพอร์ตโมดูลอื่นซึ่งมีการกำหนดตัวแปรส่วนกลางหรือตัวแปรสมาชิกคลาสให้กับ (หรือใช้) อ็อบเจ็กต์ใหม่บางอย่างคุณอาจต้องกำหนดเงื่อนไขการนำเข้านั้นในลักษณะเดียวกัน:

if __name__ ==  '__main__':
  import my_module

3

ดังที่ @Ofer กล่าวเมื่อคุณใช้ไลบรารีหรือโมดูลอื่นคุณควรนำเข้าทั้งหมดภายในไฟล์ if __name__ == '__main__':

ดังนั้นในกรณีของฉันจบลงดังนี้:

if __name__ == '__main__':       
    import librosa
    import os
    import pandas as pd
    run_my_program()

0

ในกรณีของฉันมันเป็นข้อผิดพลาดง่ายๆในโค้ดโดยใช้ตัวแปรก่อนที่จะสร้าง ควรตรวจสอบก่อนที่จะลองใช้วิธีแก้ไขปัญหาข้างต้น ทำไมฉันถึงได้รับข้อความแสดงข้อผิดพลาดนี้พระเจ้าทรงทราบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.