Проблемы с пространством имен Python при параллельном ipython

Я начинаю экспериментировать с параллельными инструментами IPython, и у меня возникла проблема. Я запускаю свои python-движки с помощью:

ipcluster start -n 3

Тогда следующий код работает нормально:

from IPython.parallel import Client

def dop(x):
    rc = Client()
    dview = rc[:]
    dview.block=True
    dview.execute('a = 5')
    dview['b'] = 10
    ack = dview.apply(lambda x: a+b+x, x)
    return ack

ack = dop(27)
print ack

возвращает [42, 42, 42] как следует. Но если я разбью код на разные файлы: dop.py:

from IPython.parallel import Client

def dop(x):
    rc = Client()
    dview = rc[:]
    dview.block=True
    dview.execute('a = 5')
    dview['b'] = 10
    print dview['a']
    ack = dview.apply(lambda x: a+b+x, x)
    return ack

и попробуйте следующее:

from dop import dop
ack = dop(27)
print ack

Я получаю ошибки от каждого движка:

[0:apply]: NameError: global name 'a' is not defined
[1:apply]: NameError: global name 'a' is not defined
[2:apply]: NameError: global name 'a' is not defined

Я не понимаю ... почему я не могу поместить функцию в другой файл и импортировать ее?

10 голосов | спросил I.P. Freeley 2 J0000006Europe/Moscow 2012, 00:59:29

1 ответ


0

Быстрый ответ: украсьте свою функцию с помощью @interactive из IPython.parallel.util [1], если вы хотите, чтобы он имел доступ к глобальному пространству имен движка:

из IPython.parallel.util интерактивный импорт
f = интерактивный (лямбда х: а + б + х)
ack = dview.apply (f, x)

Фактическое объяснение:

Пространство имен пользователя IPython - это модуль __main__. Это где код запускается, когда вы делаете execute('a = 5').

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

лам = лямбда х: а + б + х
Lam .__ module__
'__главный__'

Когда Механизм десериализует функцию, он делает это в соответствующем глобальном пространстве имен для модуля функции, поэтому функции, определенные в __main__ в ваш клиент также определен в __main__ на движке и, таким образом, имеет доступ к a.

После того, как вы поместили его в файл и импортировали его, функции больше не присоединяются к __main__, а к модулю dop:

из доп импорт импорт доп
Присадка .__ module__
'DOP'

Все функции, традиционно определенные в этом модуле (включая лямбды), будут иметь это значение, поэтому, когда они будут распакованы в Engine, их глобальное пространство имен будет таким же, как у dop, не __main__, поэтому ваше 'a' недоступно.

По этой причине IPython предоставляет простой декоратор @interactive, который приводит к распаковке любой функции, как если бы она была определена в __main__, независимо от того, где функция определена.

Для примера различия возьмем это dop.py:

из IPython.parallel Импорт Клиента
из IPython.parallel.util интерактивный импорт

а = 1

def dop (x):
    rc = Client ()
    dview = rc [:]
    dview ['a'] = 5
    f = лямбда х: а + х
    вернуть dview.apply_sync (f, x)

def idop (x):
    rc = Client ()
    dview = rc [:]
    dview ['a'] = 5
    f = интерактивный (лямбда х: а + х)
    вернуть dview.apply_sync (f, x)

Теперь dop будет использовать «a» из модуля dop и idop будет использовать 'a' из ваших пространств имен движка. Единственное различие между ними заключается в том, что переданная для применения функция заключена в ---- +: = 17 = + ---- :

из доп импортировать доп, идоп
печать доп (5) # 6
распечатать idop (5) # 10

[1]: В IPython> = 0,13 (готовящийся к выпуску) @interactive также доступно как @interactive, где это всегда должно было быть.

ответил minrk 2 J0000006Europe/Moscow 2012, 06:40:16

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132