2016-08-15 5 views
1

Я пытаюсь разделить задачу поиска исторических данных о ценах на акции для списка символов с помощью Pool из библиотеки multiprocessing.Переменные Python не определены после if __name__ == '__main__'

Это отлично работает, пока я не попытаюсь использовать данные, которые я возвращаю. У меня установлена ​​моя функция hist_price, и она выводится в список-of-dicts pcl. Я могу print(pcl), но это было безупречно, но если я попытаюсь сделать print(pcl) после блока if __name__=='__main__':, он взорвется, сказав, что pcl не определено. Я попытался объявить global pcl в нескольких местах, но это не имеет значения.

from multiprocessing import Pool 

syms = ['List', 'of', 'symbols'] 

def hist_price(sym): 
    #... lots of code looking up data, calculations, building dicts... 
    stlh = {"Sym": sym, "10D Max": pcmax, "10D Min": pcmin} #simplified 
    return stlh 

#global pcl 
if __name__ == '__main__': 
    pool = Pool(4) 
    #global pcl 
    pcl = pool.map(hist_price, syms) 
    print(pcl) #this works 
    pool.close() 
    pool.join() 

print(pcl) #says pcl is undefined 

#...rest of my code, dependent on pcl... 

Я также попытался удалить if __name__=='__main__': блок, но это дает мне RuntimeError говорил мне специально, чтобы вернуть его. Есть ли другой способ вызова переменных для использования вне блока if?

+0

У вас есть 'if __name __ == '__ main __':' потому что вы используете сценарий с терминала или по какой-то другой причине? –

+0

@MosesKoledoye Вероятно, потому что OP использует многопроцессорную обработку. – poke

+0

@poke oh Ok. по-видимому, так. –

ответ

2

Я думаю, что есть две части вашей проблемы. Первое: «Что случилось с pcl в текущем коде?», А второе - «зачем мне нужен блок защиты if __name__ == "__main__"?».

Позволяет их упорядочить. Проблема с переменной pcl заключается в том, что она определена только в блоке if, поэтому, если модуль загружается без запуска в качестве скрипта (который задает __name__ == "__main__"), он не будет определяться при запуске более позднего кода.

Чтобы исправить это, вы можете изменить способ структурирования вашего кода. Простейшим решением было бы защитить другие биты кода, которые используют pcl в блоке if __name__ == "__main__" (например, отступы их все под текущим блоком, возможно). Альтернативным решением было бы поместить код, который использует pcl в функции (которые могут быть объявлены вне защитного блока), а затем вызывать функции из блока if __name__ == "__main__". Это будет выглядеть примерно так:

def do_stuff_with_pcl(pcl): 
    print(pcl) 

if __name__ == "__main__": 
    # multiprocessing code, etc 
    pcl = ... 
    do_stuff_with_pcl(pcl) 

А почему этот вопрос возник в первую очередь, конечная причина использует multiprocessing модуль на Windows. Вы можете прочитать о проблеме в the documentation.

Когда многопроцессорность создает новый процесс для своего Pool, ему необходимо инициализировать этот процесс с копией состояния текущего модуля. Поскольку Windows не имеет fork (который автоматически копирует память родительского процесса в дочерний процесс), Python должен настроить все с нуля. В каждом дочернем процессе он загружает модуль из своего файла, и если код верхнего уровня модуля пытается создать новый Pool, у вас будет рекурсивная ситуация, когда каждый дочерний процесс начнет создавать новый набор дочерние процессы.

multiprocessing код имеет несколько охранников против этого, я думаю, что (так что вы не fork bomb будут сами из простой невнимательности), но вам все еще нужно, чтобы сделать некоторые работы самостоятельно тоже с помощью if __name__ == "__main__" для защиты любого кода, не должны выполняться в дочерних процессах.

+0

Этот процесс выполняется в начале моего кода, а остальная часть зависит от 'pcl'.Я надеялся избежать размещения всего остального кода в блоке 'if', если бы мог это сделать. Я попытался объявить 'pcl' (с и без' global') вне блока 'if', но он по-прежнему выглядит как два отдельных экземпляра. – wampthing2

+0

@ wampthing2: я обновил свой ответ, чтобы узнать больше о том, что это за проблема, и более подробно о том, как ее исправить. В ролях: не делайте слишком много вещей на верхнем уровне, так как вам нужно будет защищать это с помощью 'if __name__ ==" __main __ "'. – Blckknght