Hier ist ein kleiner Ausschnitt, den ich kam mit
def jobs_manager():
from IPython.lib.backgroundjobs import BackgroundJobManager
from IPython.core.magic import register_line_magic
from IPython import get_ipython
jobs = BackgroundJobManager()
@register_line_magic
def job(line):
ip = get_ipython()
jobs.new(line, ip.user_global_ns)
return jobs
Es verwendet das integrierte IPython-Modul IPython.lib.backgroundjobs
. Der Code ist also klein und einfach und es werden keine neuen Abhängigkeiten eingeführt.
Ich benutze es wie folgt aus:
jobs = jobs_manager()
%job [fetch_url(_) for _ in urls] # saves html file to disk
Starting job # 0 in a separate thread.
Dann Sie den Zustand mit überwachen können:
jobs.status()
Running jobs:
1 : [fetch_url(_) for _ in urls]
Dead jobs:
0 : [fetch_url(_) for _ in urls]
Wenn Auftrag fehlschlägt Sie Stack-Trace mit
jobs.traceback(0)
Es gibt inspizieren keine Möglichkeit, einen Job zu töten. So verwende ich sorgfältig mit diesem schmutzigen Hack:
def kill_thread(thread):
import ctypes
id = thread.ident
code = ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(id),
ctypes.py_object(SystemError)
)
if code == 0:
raise ValueError('invalid thread id')
elif code != 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(id),
ctypes.c_long(0)
)
raise SystemError('PyThreadState_SetAsyncExc failed')
Es wirft SystemError
in einem bestimmten Thread.So einen Job zu töten ich
tun
kill_thread(jobs.all[1])
Um alle laufenden Aufträge zu töten ich
for thread in jobs.running:
kill_thread(thread)
Ich mag verwenden %job
mit Widget-basierte Fortschrittsbalken https://github.com/alexanderkuk/log-progress wie folgt aus:
%job [fetch_url(_) for _ in log_progress(urls, every=1)]
http://g.recordit.co/iZJsJm8BOL.gif
Man kann sogarverwenden 210 statt multiprocessing.TreadPool
:
for chunk in get_chunks(urls, 3):
%job [fetch_url(_) for _ in log_progress(chunk, every=1)]
http://g.recordit.co/oTVCwugZYk.gif
Einige offensichtliche Probleme mit diesem Code:
Sie nicht beliebigen Code in %job
verwenden können. Es kann keine Zuweisungen geben und nicht zum Beispiel drucken. Also verwende ich es mit Routinen, die Ergebnisse auf der Festplatte speichern
Manchmal funktioniert schmutzig Hack in kill_thread
nicht. Ich denke, das ist, warum IPython.lib.backgroundjobs
diese Funktionalität nicht von Entwurf hat. Wenn der Thread einen Systemaufruf wie sleep
oder read
ausführt, wird die Ausnahme ignoriert.
Es verwendet Threads. Python hat GIL, so %job
kann nicht für einige schwere Berechnungen verwendet werden, die
@minrk in Python-Bytecode nehmen Könnten Sie an dieser Antwort suchen Sie und sehen, ob es noch andere Probleme mit dieser Lösung, dass ich nicht glaube, Über? – alexanderkuk