Ausgabe vom Jupyter-Kernel in (i) Python-Skript erhalten

Ich möchte mehrere Kernel in einer einzigen ipython-Sitzung öffnen, Code auf diesen Kerneln ausführen und dann die Ergebnisse sammeln. Aber ich kann nicht herausfinden, wie man die Ergebnisse sammelt oder sogar stdout / stderr sieht. Wie kann ich diese Dinge tun?

Was ich bisher habe

Ich habe die ersten beiden Schritte (Kernel öffnen und Code darauf ausführen) mit folgendem Code ausgeführt:

from jupyter_client import MultiKernelManager
kernelmanager = MultiKernelManager()
remote_id = kernelmanager.start_kernel('python3')
remote_kernel = kernelmanager.get_kernel(remote_id)
remote = remote_kernel.client()
sent_msg_id = remote.execute('2+2')

[Ich freue mich über Vorschläge zur Verbesserung oder zum Schließen dieser Kernel und Clients.]

Hier,python3 kann der Name eines von mir eingerichteten Kernels sein (der in der Befehlszeile mit @ aufgelistet werden kannjupyter-kernelspec list). Und ich scheine in der Lage zu sein, irgendeinen vernünftigen Code anstelle von @ auszuführ'2+2'. Zum Beispiel kann ich in eine Datei schreiben, und diese Datei wird wirklich erstellt.

Nun, das Problem ist, wie man das Ergebnis erhält. Ich kann eine Nachricht erhalten, die anscheinend mit @ verwandt is

reply = remote.get_shell_msg(sent_msg_id)

Diese Antwort ist ein Wörterbuch wie dieses:

{'buffers': [],
 'content': {'execution_count': 2,
  'payload': [],
  'status': 'ok',
  'user_expressions': {}},
 'header': {'date': datetime.datetime(2015, 10, 19, 14, 34, 34, 378577),
  'msg_id': '98e216b4-3251-4085-8eb1-bfceedbae3b0',
  'msg_type': 'execute_reply',
  'session': 'ca4d615d-82b7-487f-88ff-7076c2bdd109',
  'username': 'me',
  'version': '5.0'},
 'metadata': {'dependencies_met': True,
  'engine': '868de9dd-054b-4630-99b7-0face61915a6',
  'started': '2015-10-19T14:34:34.265718',
  'status': 'ok'},
 'msg_id': '98e216b4-3251-4085-8eb1-bfceedbae3b0',
 'msg_type': 'execute_reply',
 'parent_header': {'date': datetime.datetime(2015, 10, 19, 14, 34, 34, 264508),
  'msg_id': '2674c61a-c79a-48a6-b88a-1f2e8da68a80',
  'msg_type': 'execute_request',
  'session': '767ae562-38d6-41a3-a9dc-6faf37d83222',
  'username': 'me',
  'version': '5.0'}}

Dies ist dokumentiert inMessaging in Jupyter. Was nicht dokumentiert ist, ist, wie dies tatsächlich verwendet wird - d. H. Welche Funktionen verwende ich, wann und wo finde ich Nachrichten usw. Ich habe gesehen,diese Frag und seine Antwort, die nützliche verwandte Informationen enthält, mich aber nicht ganz zur Antwort bringt. Unddiese Antwort bekommt auch keine sinnvolle Ausgabe.

Also, zum Beispiel habe ich versucht, die Nachricht auch mit dem @ zu bekommmsg_id im obigen Ergebnis angegeben, hängt aber nur. Ich habe alles versucht, was mir einfällt, kann aber nicht herausfinden, wie ich etwas vom Kernel zurückbekomme. Wie mache ich es? Kann ich Daten in einer Art Zeichenfolge vom Kernel zurück übertragen? Kann ich seine stdout und stderr sehen?

Hintergrun

Ich schreibe eine Ipython-Magie, um ein Code-Snippet auf entfernten Kerneln auszuführen. [Bearbeiten: Dies existiert jetzt und ist verfügbar untHie.] Die Idee ist, dass ich ein Notebook auf meinem Laptop habe und Daten von mehreren entfernten Servern sammle, indem ich einfach eine kleine magische Zelle wie diese habe:

%%remote_exec -kernels server1,server2
2+2
! hostname

Ich benutzeremote_ikernel, um einfach und automatisch eine Verbindung zu diesen Remote-Kerneln herzustellen. Das scheint gut zu funktionieren; Ich habe meinen magischen Befehl mit all seinen Schnickschnack, der hervorragend funktioniert, diese Remote-Kernel öffnet und den Code ausführt. Jetzt möchte ich einige dieser Daten von der Fernbedienung an meinen Laptop zurücksenden - vermutlich, indem ich sie auf irgendeine Weise serialisiere. Im Moment denke ichpickle.dumps undpickle.loads wäre perfekt für diesen Teil; Ich muss nur diese Bytes von einem Kernel zum anderen erzeugen und von diesen Funktionen verwenden lassen. Ich würde lieber keine tatsächlichen Dateien für das Beizen verwenden, obwohl dies möglicherweise akzeptabel wäre.

Bearbeiten

Es sieht so aus, als ob es mit etwas Monstrosität möglich wäre:

remote.get_shell_msg(remote.execute('import pickle'))
sent_msg_id = remote.execute('a=2+2', user_expressions={'output':'pickle.dumps({"a":a})'})
reply = remote.get_shell_msg(sent_msg_id)
output_bytes = reply['content']['user_expressions']['output']['data']['text/plain']
variable_dict = pickle.loads(eval(output_bytes))

Und nun,variable_dict['a'] ist nur4. Beachten Sie jedoch, dassoutput_bytes ist ein String, der diese Bytes repräsentiert, also muss es @ seevaled. Dies scheint lächerlich (und zeigt immer noch nicht, wie ich stdout bekommen würde). Gibt es einen besseren Weg? Und wie bekomme ich stdout?

Edit 2:

bwohl ich mit meinem obigen Hack unzufrieden bin, habe ich ihn erfolgreich verwendet, um ein kleines Modul mit dem Namen @ zu schreiberemote_exec wie oben beschrieben auf github gehostet. Das Modul verleiht mir einen Hauch von Ipython, mit dem ich Code auf einem oder mehreren anderen Kerneln remote ausführen kann. Dies ist ein mehr oder weniger automatischer Prozess, mit dem ich definitiv zufrieden bin - abgesehen von dem quälenden Wissen darüber, was darunter passiert.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage