Ich wüsste auch nicht wofür man wirklich *so* viele Sachen *echt* parallel bräuchte, denn ich sehe nicht wo das Vorteile bringt. Weder bei CPU noch bei I/O. Je mehr desto besser stimmt hier ja nicht, denn die Parallelität hat mit den Resourcen auch ihre Grenzen. Man hat normalerweise keine 1000 Prozessoren/Kerne oder so viele Massenspeicher das man die I/O-Last von 1000 Threads darauf verteilen könnte ohne das I/O der Flaschenhals wird und es dann eher langsamer wird als schneller.
Bei der Doku würde ich ja fast schon wieder den alten Hasen gegenüber dem Anfänger raushängen lassen, der sich einfach nicht genug mit dem Thema beschäftigen möchte. So ziemlich gleich am Anfang der Seite, ich muss dafür noch nicht einmal runters scrollen, ist `threading.enumerate()` dessen Dokumentation mit dem Satz „Return a list of all Thread objects currently alive.“ beginnt. Wobei `Thread` ein Link auf die Doku von `threading.Thread` ist, also genau die Objekte die Du haben möchtest. Nicht enthalten in der Liste sind „[…] terminated threads and threads that have not yet been started.“
Also so etwas in dieser Richtung (ungetestet):
Code: Alles auswählen
LOG.debug('Active threads with `aufgabe`: %s', len(threads))
for thread in threading.enumerate():
if hasattr(thread, 'aufgabe'):
LOG.debug(
'%r\n %r\n %r', thread, thread.aufgabe, thread.arguments
)
`Futures.result()` löst dann eine Ausnahme aus wenn die Funktion dazu eine Ausnahme ausgelöst hat. Und zwar genau diese Ausnahme:
Code: Alles auswählen
In [40]: e = concurrent.futures.ThreadPoolExecutor(10)
In [41]: def f():
...: assert False
...:
In [42]: r = e.submit(f)
In [43]: r.result()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-43-6401ee0d034b> in <module>()
----> 1 r.result()
/usr/local/lib/python2.7/dist-packages/concurrent/futures/_base.pyc in result(self, timeout)
398 raise CancelledError()
399 elif self._state == FINISHED:
--> 400 return self.__get_result()
401
402 self._condition.wait(timeout)
/usr/local/lib/python2.7/dist-packages/concurrent/futures/_base.pyc in __get_result(self)
357 def __get_result(self):
358 if self._exception:
--> 359 reraise(self._exception, self._traceback)
360 else:
361 return self._result
/usr/local/lib/python2.7/dist-packages/concurrent/futures/_compat.pyc in reraise(exc, traceback)
105 def reraise(exc, traceback):
106 locals_ = {'exc_type': type(exc), 'exc_value': exc, 'traceback': traceback}
--> 107 exec('raise exc_type, exc_value, traceback', {}, locals_)
108 else:
109 def reraise(exc, traceback):
/usr/local/lib/python2.7/dist-packages/concurrent/futures/thread.pyc in run(self)
59
60 try:
---> 61 result = self.fn(*self.args, **self.kwargs)
62 except BaseException:
63 e, tb = sys.exc_info()[1:]
<ipython-input-41-cfcdc8007ab4> in f()
1 def f():
----> 2 assert False
AssertionError:
Code: Alles auswählen
In [44]: r = e.submit(f)
In [45]: concurrent.futures.wait([r])
Out[45]: DoneAndNotDoneFutures(done=set([<Future at 0xb418acc state=finished raised AssertionError>]), not_done=set([]))
In [46]: _.done.pop().result()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-46-d26524687e7c> in <module>()
----> 1 _.done.pop().result()
/usr/local/lib/python2.7/dist-packages/concurrent/futures/_base.pyc in result(self, timeout)
398 raise CancelledError()
399 elif self._state == FINISHED:
--> 400 return self.__get_result()
401
402 self._condition.wait(timeout)
/usr/local/lib/python2.7/dist-packages/concurrent/futures/_base.pyc in __get_result(self)
357 def __get_result(self):
358 if self._exception:
--> 359 reraise(self._exception, self._traceback)
360 else:
361 return self._result
/usr/local/lib/python2.7/dist-packages/concurrent/futures/_compat.pyc in reraise(exc, traceback)
105 def reraise(exc, traceback):
106 locals_ = {'exc_type': type(exc), 'exc_value': exc, 'traceback': traceback}
--> 107 exec('raise exc_type, exc_value, traceback', {}, locals_)
108 else:
109 def reraise(exc, traceback):
/usr/local/lib/python2.7/dist-packages/concurrent/futures/thread.pyc in run(self)
59
60 try:
---> 61 result = self.fn(*self.args, **self.kwargs)
62 except BaseException:
63 e, tb = sys.exc_info()[1:]
<ipython-input-41-cfcdc8007ab4> in f()
1 def f():
----> 2 assert False
AssertionError: