Тупик Python, связанный с упаковкой и Mayavi?

У меня есть любопытная проблема, и я надеюсь, что кто-нибудь сможет пролить свет на нее.

У меня есть сложный фрагмент кода, который начинался как каталог, полный скриптов, который я решил переработать в пакет. Это изменение кода, по-видимому, послужило причиной появления странных тупиковых ситуаций.

Ниже представлена ​​попытка канонического воспроизведения проблемы; что не удается, в том смысле, что этот код работает, как ожидалось. Фактическое воспроизведение проблемы может потребовать большого количества кода; но я не могу на всю жизнь представить, что отличается от фрагмента кода оскорбления в контексте.

import numpy as np
from scipy.sparse import csr_matrix
from threading import Thread

def dummy():
    print 'this is printed'
    I = np.eye(3)
    print 'all is still fine'
    csr_matrix(I)
    print 'this is never printed; csr_matrix appears to be a trigger for deadlock'
    print np.ones(4)
    print 'same problem; somehow, printing ndarrays is no longer cool either'

thr = Thread(target=dummy)
thr.start()

Возможно, этот краткий комментарий в документации связан? Я не уверен, что полностью понимаю то, что здесь говорится

http://docs.python.org/2/library/threading#importing-in-threaded-code

Во-первых, кроме основного модуля, импорт не должен иметь побочного эффекта в виде создания нового потока и последующего ожидания этого потока каким-либо образом. Несоблюдение этого ограничения может привести к тупиковой ситуации, если порожденный поток прямо или косвенно попытается импортировать модуль.

Некоторый контекст: я использую python 2.7, numpy 1.8, где я пытаюсь создать этот новый поток из потока mayavi / traitsui (который я не понимаю, почему он должен быть актуальным и который работал нормально до структуры пакета, но хорошо) . Кроме того, в моем порожденном потоке есть масса кода numpy / scipy, который отлично работает; это просто печать ndarrays и создание разреженных матриц, которые до сих пор оказались триггерами для тупиковой ситуации.

Я подозреваю какое-то фанковое взаимодействие с mayavi, поскольку закрытие окна mayavi заставляет все заблокированные потоки снова запускаться. Возможно, этот конкретный оператор запускает поток Python, чтобы уступить потоку Mayavi, но они каким-то образом не могут снова получить фокус?

Мы очень ценим любые подсказки, которые приведут к дальнейшему сужению этой тайны!


person Eelco Hoogendoorn    schedule 15.12.2013    source источник
comment
Трудно сказать, поскольку проблема, вероятно, связана с деталями вашего кода, которые вы здесь не воспроизводили. Вы join() ведете какие-либо из этих тем? Вы запускаете их на верхнем уровне модуля, как в примере, который вы нам дали? Если вы делаете обе эти вещи, то это то, что вам не следует делать в комментарии из документации. Существует глобальная блокировка импорта, которая удерживается во время выполнения кода модуля. Вызов csr_matrix() таким образом вызывает импорт, поэтому он также попытается получить блокировку импорта. Возникает тупик. Не делай этого.   -  person Robert Kern    schedule 16.12.2013
comment
Спасибо за помощь. Вот как я понял документы; но я не делаю ни того, ни другого. Я никуда не присоединяюсь. Возможно, майави делает где-то за кулисами; но документация не об этом предупреждает, не так ли? Поток запускается из метода в объекте пользовательского интерфейса в ответ на ввод данных пользователем. Кроме того, csr_matrix уже давно импортирован где-то еще; он должен быть кэширован, так что блокировка импорта все еще вступает в силу?   -  person Eelco Hoogendoorn    schedule 17.12.2013
comment
Также; какие-либо подсказки относительно того, что делает csr_matrix и ndarray .__ repr__ особенными? Почему мой поток успешно проходит через код, который проходит повсюду; numpy scipy и целый ряд импортов, но постоянно застревает независимо от того, где я вызываю любую из этих двух функций?   -  person Eelco Hoogendoorn    schedule 17.12.2013
comment
Вызов csr_matrix() на плотном ndarray вызове импорта. Если вы можете предложить полный пример, демонстрирующий проблему, я могу помочь.   -  person Robert Kern    schedule 17.12.2013
comment
Когда вы говорите, что используете Mayavi, вы имеете в виду, что используете mlab.show() в своем скрипте, а не интегрируете свой код в приложение Mayavi?   -  person Robert Kern    schedule 17.12.2013
comment
Но что особенного в этом импорте? В моем коде должно быть буквально сотни операций импорта, которые не вызывают проблем. Я использую экземпляр MlabSceneModel из классифицированного класса. Я использовал configure_traits () для этого классифицированного класса из main, запуская основной внутренний поток, но после рефакторинга моего проекта в пакет это больше не происходит в main, а в модуль, импортированный из main. Это может иметь какое-то отношение к ситуации.   -  person Eelco Hoogendoorn    schedule 17.12.2013
comment
Ах; вызов configure_traits из того, что сейчас является новым основным, решает проблему. Кроме того, размещение вызова configure_traits () внутри фиктивной функции, а не непосредственно в модуле, решает проблему (более элегантным способом). По-видимому, это ошибка майави или, по крайней мере, ошибка. Опять же, я не тот, кто где-либо соединяет потоки, и все примеры Mayavi с радостью рекомендуют размещение configure_traits на уровне модуля. Я все еще не понимаю, что делает csr_matrix и ndarray .__ repr__ особенными; но, по крайней мере, все снова работает, и это начало. Спасибо за ответ!   -  person Eelco Hoogendoorn    schedule 17.12.2013
comment
В примерах mayavi показаны сценарии, которые нужно выполнить, а не модули, которые нужно импортировать.   -  person Robert Kern    schedule 17.12.2013
comment
Тем не менее, это несколько непонятно, что то, что должно быть чисто организационным делом, может иметь такие положительные и отрицательные последствия.   -  person Eelco Hoogendoorn    schedule 17.12.2013
comment
Впрочем, Ypu правы; это не ошибка Mayavi. Просто попалась.   -  person Eelco Hoogendoorn    schedule 17.12.2013


Ответы (1)


Судя по вашим комментариям, похоже, что вы запускаете цикл событий пользовательского интерфейса на верхнем уровне одного из ваших вспомогательных модулей. Это не лучшая идея, потому что она вызывает точно такие же проблемы, о которых упоминается в документации. import foo никогда не должен запускать цикл событий пользовательского интерфейса. Проблема в том, что основной поток захватывает блокировку импорта для обработки импорта модуля. Этот модуль запускает цикл событий пользовательского интерфейса перед завершением импорта. По сути, это та же ситуация, что и ожидание завершения других потоков; вы ждете завершения цикла пользовательского интерфейса. Если ваш пользовательский интерфейс запускает другие потоки, код, который выполняется в других потоках, не сможет ничего импортировать (и csr_matrix(), и ndarray.__repr__() импортируют другие модули), потому что основной поток все еще удерживает блокировку импорта.

person Robert Kern    schedule 17.12.2013
comment
Я понимаю; configure_traits создает поток, а затем ожидает его, что противоречит правилам, указанным в документации (не повредит, если в документации mayavi это подчеркнуто). Однако я не понимаю, что взаимоблокировка возникает только при использовании очень узкого подмножества функций (опять же, тонны кода, заваленного импортом, выполняются без проблем, как в потоке mayavi, так и в его дочернем потоке). - person Eelco Hoogendoorn; 17.12.2013
comment
Я все еще не могу сказать, что полностью понимаю, что здесь происходит, и должен сказать, что я несколько разочарован питонностью всего этого. Но, несмотря на это, если внимательно прочитать документы и придерживаться их, проблема решится. Спасибо за назад и вперед; хотя я в конце концов понял это, я плохо принимаю это как ответ. - person Eelco Hoogendoorn; 17.12.2013
comment
configure_traits() не создает поток. Он просто запускает цикл пользовательского интерфейса и не возвращается, пока цикл пользовательского интерфейса не завершится. Все циклы пользовательского интерфейса ведут себя так. Об этом говорится в документации configure_traits(). Я ожидаю, что ни один из потоков, которые вы используете, на самом деле не импортирует вещи внутри потока, такие как вызов csr_matrix() или ndarray.__repr__() do, просто используя модули, которые были импортированы в пространство имен модуля до запуска потока. - person Robert Kern; 17.12.2013
comment
У меня создалось впечатление, что все приложения с характеристиками используют несколько потоков внутри себя? Но несмотря ни на что; вызов configure_traits () блокируется, поэтому мой рабочий поток по-прежнему косвенно является побочным эффектом импорта, поэтому блокировка импорта все еще на месте. - person Eelco Hoogendoorn; 18.12.2013
comment
Но если configure_traits () не создает поток, разве это не делает документацию неполной? Предполагается, что проблема возникает в результате создания потока на уровне модуля и последующего присоединения к нему. Но опять же; Я не жду никаких потоков. Что дает mayavi / traits? Я бы сказал, что предупреждение в документации недостаточно общее; следует избегать не только присоединения к потокам, но и любого вида блокирующего кода, такого как цикл пользовательского интерфейса, который вызовет проблемы. Это подразумевается, когда вы понимаете, что происходит; но я почти решил, что это предостережение не имеет для меня никакого отношения, потому что я все равно не присоединялся ни к каким обсуждениям! - person Eelco Hoogendoorn; 18.12.2013
comment
Я думаю, что, как предполагает Роберт Керн, ваша проблема не имеет ничего общего с майави в данном случае. Однако из-за того, насколько точно mayavi должен управлять своими сценами, все еще остается много ошибок, которые не являются ошибками (и, возможно, пара настоящих ошибок) с mayavi, когда ваш графический интерфейс становится сложным и пытается делать много вещей с потоки. Как правило, для создания приложений с графическим интерфейсом на основе Mayavi часто необходимо явно управлять порядком, в котором что-то происходит. То есть, я думаю, что любая оговорка в документации о блокировке является хорошей идеей, поскольку она имеет прямое отношение к mayavi. - person aestrivex; 18.12.2013