Skip to content

Instantly share code, notes, and snippets.

@micahscopes
Created November 16, 2017 04:49
Show Gist options
  • Save micahscopes/2f523a8f485d3fe53cc32cef450ca27f to your computer and use it in GitHub Desktop.
Save micahscopes/2f523a8f485d3fe53cc32cef450ca27f to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# User friendly multiprocessing in Jupyter with ipywidgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### by Micah ([@micahscopes](http://wondering.xyz))\n",
"11/15/2017"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### A stoppable `multiprocessing.Process` subclass that displays its status:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"run_control": {
"frozen": false,
"read_only": false
}
},
"outputs": [],
"source": [
"from multiprocessing import Process, Event\n",
"from ipywidgets import Output\n",
"from IPython.display import display\n",
"from time import sleep\n",
"\n",
"class ProcessWithStatus(Process):\n",
" def __init__(self):\n",
" self.output = Output()\n",
" self.exit = Event()\n",
" self.exited = Event()\n",
" super().__init__()\n",
" \n",
" with self.output:\n",
" print(self)\n",
" \n",
" def status(self):\n",
" display(self.output)\n",
" \n",
" def start(self): \n",
" super().start()\n",
" with self.output:\n",
" print(self)\n",
" print('running...')\n",
" \n",
" def stop(self):\n",
"# with self.output:\n",
" with self.output:\n",
" print('letting work finish before stopping...')\n",
" self.exit.set()\n",
" \n",
" self.exited.wait()\n",
" sleep(0.1) # Need to wait a little bit before the status is `stopped`\n",
" with self.output:\n",
" print(self)\n",
" \n",
" def work(self):\n",
" sleep(5)\n",
" pass\n",
" \n",
" def run(self):\n",
" while not self.exit.is_set():\n",
" # do the work\n",
" self.work()\n",
" \n",
" # when the work is done, signal that we are finished\n",
" self.exited.set()\n",
"\n",
"p = ProcessWithStatus()\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7849905d904142a79b2a73c7731bfd86"
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p.status()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"p.start()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"p.stop()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7849905d904142a79b2a73c7731bfd86"
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p.status()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Adding start and stop buttons:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from ipywidgets import Button\n",
"\n",
"class ProcessWithControls(ProcessWithStatus):\n",
" def __init__(self):\n",
" self.start_button = Button(description='start')\n",
" self.start_button.on_click(lambda evt: self.start())\n",
" self.stop_button = Button(description='stop')\n",
" self.stop_button.on_click(lambda evt: self.stop())\n",
" \n",
" super().__init__()\n",
" \n",
" def controls(self):\n",
" display(self.start_button)\n",
" display(self.stop_button)\n",
" \n",
" def control_panel(self):\n",
" self.controls()\n",
" self.status()\n",
" \n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "89711ccf151b4903b4c686b802e743e2"
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p = ProcessWithControls()\n",
"p.status()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "58330af2e099454090fedc2013f0ef55"
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "abe76bba34364dd5be13aab7fdb01207"
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p.controls()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "58330af2e099454090fedc2013f0ef55"
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "abe76bba34364dd5be13aab7fdb01207"
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "89711ccf151b4903b4c686b802e743e2"
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p.control_panel()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### P.S. there's no reason you couldn't do something like this with multiple threads!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.2"
},
"latex_envs": {
"LaTeX_envs_menu_present": true,
"autocomplete": true,
"bibliofile": "biblio.bib",
"cite_by": "apalike",
"current_citInitial": 1,
"eqLabelWithNumbers": true,
"eqNumInitial": 1,
"hotkeys": {
"equation": "Ctrl-E",
"itemize": "Ctrl-I"
},
"labels_anchors": false,
"latex_user_defs": false,
"report_style_numbering": false,
"user_envs_cfg": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@the-moog
Copy link

the-moog commented Jan 5, 2020

Sadly, it seem this no longer works, at least on windows (py 3.8.1/win64).
p.start() returns error: PicklingError: Can't pickle : it's not the same object as builtins.input

@micahscopes
Copy link
Author

micahscopes commented Jan 6, 2020 via email

@snownstone
Copy link

It still works perfectly (ubuntu 20.0, python 3.8.7). Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment