многопроцессорная карта продолжает выполнять скрипт, а не функцию

#python #python-3.x #multiprocessing

#python #python-3.x #многопроцессорная обработка

Вопрос:

эй, я пытаюсь ускорить свой код, используя пул многопроцессорных процессов, и теоретически это:

     def render_frame(i):
        #os.system(f'python main.py video_imgs/out{i}.png {convo}')
        print(f'done {i}')
    
    if __name__ == '__main__':
        pic_list = list(range(1,num_of_pics))
        with Pool(10) as p:
            s = p.map(render_frame,pic_list)
 

затем должно быть напечатано число i, но когда я запускаю скрипт, он просто выдает мне приглашение ввода, которое у меня есть в начале скрипта 10 раз, а именно ->

     from multiprocessing import Pool
    import sys
    import os
    import time
    
    if(len(sys.argv) > 1):
        vidLoc = sys.argv[1]
        convo = sys.argv[2]
    else:
        vidLoc = input('video: ') #! <-- this is being repeated 10 times
        convo = input('convolute cfg file: ')
 

любая помощь? Спасибо

Комментарии:

1. Вызов os.system() прокомментирован в предоставленном вами коде. Вы уверены, что предоставили правильный фрагмент кода?

2. @ThiagoF. Pappacena да, это правильный фрагмент, который я тестировал и проверял, была ли это проблема, но безрезультатно

3. Если вы нажимаете на другую часть в main.py , это означает, что, вероятно, из этой строки ему не было передано никаких аргументов: #os.system(f'python main.py video_imgs/out{i}.png {convo}') <- что {convo} в этом?

Ответ №1:

В системах, которые используют 'spawn' в качестве multiprocessing метода запуска по умолчанию (Windows, macOS), вы должны охранять все «основные скриптовые» поведения под if __name__ == '__main__': защитой. 'spawn' Метод имитирует a fork путем импорта основного модуля в каждый дочерний процесс, но без __main__ имени; если вы выполняете такие вещи, как вызов input вне guard, он будет выполняться в ваших дочерних процессах. Как правило, вы должны придерживаться простого импорта и определений функций / классов / констант вне защиты, никогда не делайте ничего «активного», если вы не находитесь под охраной (например, избегайте вызова функций с наблюдаемыми побочными эффектами, такими как input ).

Защитите input код должным образом (вы можете просто опустить его, поскольку странно разрешать необязательные аргументы командной строки, которые вы запрашиваете в противном случае, и раздражает, что они отражены в дочерних процессах), и если вы должны использовать input , найдите другие способы инициализации переменных в дочернем процессе (например, с помощьюсредства initializer функции с initargs , оба являются необязательными аргументами для Pool ).

Грубый пример (ваш неполный код затрудняет точное сопоставление):

 from multiprocessing import Pool
import sys
import os
import time

def render_frame(i):
    #os.system(f'python main.py video_imgs/out{i}.png {convo}')
    print(f'done {i}')

def set_globals(v, c):
    global vidLoc, convo
    vidLoc = v
    convo = c

if __name__ == '__main__':
    if len(sys.argv) > 1:
        vidLoc = sys.argv[1]
        convo = sys.argv[2]
    else:
        vidLoc = input('video: ') #! <-- this is being repeated 10 times
        convo = input('convolute cfg file: ')

    pic_list = list(range(1,num_of_pics))
    with Pool(10, initializer=set_globals, initargs=(vidLoc, convo)) as p:
        s = p.map(render_frame,pic_list)