#python #python-2.7 #python-multiprocessing #python-unittest
#python #python-2.7 #python-многопроцессорная обработка #python-unittest
Вопрос:
У меня есть очень простой тестовый инструмент, который создает и закрывает тестовый класс ‘APMSim’ в разных потоках, класс не может быть выбран, поэтому я должен использовать многопроцессорный Pool.imap, чтобы избежать их передачи между процессами:
class APMSimFixture(TestCase):
def setUp(self):
self.pool = multiprocessing.Pool()
self.sims = self.pool.imap(
apmSimUp,
range(numCores)
)
def tearDown(self):
self.pool.map(
simDown,
self.sims
)
def test_empty(self):
pass
Однако, когда я запускаю пустой модуль Python, я сталкиваюсь со следующей ошибкой:
Error
Traceback (most recent call last):
File "/home/peng/git/datapassport/spookystuff/mav/pyspookystuff_test/mav/__init__.py", line 87, in tearDown
self.sims
File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
Почему это может произойти? Есть ли исправление для этого?
Ответ №1:
multiprocessing
повторно вызывает исключение из вашей рабочей функции / дочернего процесса в родительском процессе, но при передаче от дочернего к родительскому процессу он теряет трассировку. Проверьте свою рабочую функцию, именно этот код идет не так. Это может помочь взять любую вашу рабочую функцию и изменить:
def apmSimUp(...):
... body ...
Для:
import traceback
def apmSimUp(...):
try:
... body ...
except:
traceback.print_exc()
raise
Это явно выводит полную исходную трассировку исключения (затем позволяет ему нормально распространяться), чтобы вы могли видеть, в чем настоящая проблема.
Комментарии:
1. Большое спасибо! Но это также означает, что многопроцессорная обработка — это плохо разработанная библиотека. Хорошая библиотека не будет скрывать информацию об ошибках
2. Кроме того, поскольку этот блок используется так много раз, я хотел бы сделать его аннотацией функции, но при этом теряется возможность выбора функции, есть ли способ сделать его кратким и одновременно отображать информацию об ошибках?
3. @tribbloid: Нетривиально пересылать полную информацию стека от дочернего элемента к родительскому, но я думаю, что в Py3 это действительно может исправить; используйте 7-летний Python, вы получите больше причуд. Вы могли бы немного обмануть бит аннотации и просто передать функцию в качестве аргумента оболочке;
map(mywrapper, zip(itertools.repeat(realfunc), origarguments))
, гдеmywrapper
просто есть телоtry
блока, содержащееrealfunc, arg = args
,realfunc(arg)
.