Using Dill.ipynb
533 lines
| 26.6 KiB
| text/plain
|
TextLexer
MinRK
|
r13638 | { | |
"metadata": { | |||
"gist_id": "5241793", | |||
"name": "" | |||
}, | |||
"nbformat": 3, | |||
"nbformat_minor": 0, | |||
"worksheets": [ | |||
{ | |||
"cells": [ | |||
{ | |||
"cell_type": "heading", | |||
"level": 1, | |||
"metadata": {}, | |||
"source": [ | |||
"Using dill to pickle anything" | |||
] | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"IPython.parallel doesn't do much in the way of serialization.\n", | |||
"It has custom zero-copy handling of numpy arrays,\n", | |||
"but other than that, it doesn't do anything other than the bare minimum to make basic interactively defined functions and classes sendable.\n", | |||
"\n", | |||
"There are a few projects that extend pickle to make just about anything sendable, and one of these is [dill](http://www.cacr.caltech.edu/~mmckerns/dill).\n", | |||
"\n", | |||
"To install dill:\n", | |||
" \n", | |||
MinRK
|
r13878 | " pip install --pre dill" | |
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"First, as always, we create a task function, this time with a closure" | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"def make_closure(a):\n", | |||
" \"\"\"make a function with a closure, and return it\"\"\"\n", | |||
" def has_closure(b):\n", | |||
" return a * b\n", | |||
" return has_closure" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 1 | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"closed = make_closure(5)" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 2 | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"closed(2)" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"metadata": {}, | |||
"output_type": "pyout", | |||
"prompt_number": 3, | |||
"text": [ | |||
"10" | |||
] | |||
} | |||
], | |||
"prompt_number": 3 | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"import pickle" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 4 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"Without help, pickle can't deal with closures" | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"pickle.dumps(closed)" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"ename": "PicklingError", | |||
MinRK
|
r13878 | "evalue": "Can't pickle <function has_closure at 0x10412c6e0>: it's not found as __main__.has_closure", | |
MinRK
|
r13638 | "output_type": "pyerr", | |
"traceback": [ | |||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mPicklingError\u001b[0m Traceback (most recent call last)", | |||
"\u001b[1;32m<ipython-input-5-0f1f376cfea0>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mpickle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mclosed\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", | |||
"\u001b[1;32m/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.pyc\u001b[0m in \u001b[0;36mdumps\u001b[1;34m(obj, protocol)\u001b[0m\n\u001b[0;32m 1372\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mdumps\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mprotocol\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1373\u001b[0m \u001b[0mfile\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mStringIO\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1374\u001b[1;33m \u001b[0mPickler\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfile\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mprotocol\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdump\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1375\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mfile\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetvalue\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1376\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", | |||
"\u001b[1;32m/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.pyc\u001b[0m in \u001b[0;36mdump\u001b[1;34m(self, obj)\u001b[0m\n\u001b[0;32m 222\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mproto\u001b[0m \u001b[1;33m>=\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 223\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mPROTO\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mchr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mproto\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 224\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msave\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 225\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mSTOP\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 226\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", | |||
"\u001b[1;32m/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.pyc\u001b[0m in \u001b[0;36msave\u001b[1;34m(self, obj)\u001b[0m\n\u001b[0;32m 284\u001b[0m \u001b[0mf\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdispatch\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mt\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 285\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 286\u001b[1;33m \u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# Call unbound method with explicit self\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 287\u001b[0m \u001b[1;32mreturn\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 288\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", | |||
"\u001b[1;32m/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.pyc\u001b[0m in \u001b[0;36msave_global\u001b[1;34m(self, obj, name, pack)\u001b[0m\n\u001b[0;32m 746\u001b[0m raise PicklingError(\n\u001b[0;32m 747\u001b[0m \u001b[1;34m\"Can't pickle %r: it's not found as %s.%s\"\u001b[0m \u001b[1;33m%\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 748\u001b[1;33m (obj, module, name))\n\u001b[0m\u001b[0;32m 749\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 750\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mklass\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |||
MinRK
|
r13878 | "\u001b[1;31mPicklingError\u001b[0m: Can't pickle <function has_closure at 0x10412c6e0>: it's not found as __main__.has_closure" | |
MinRK
|
r13638 | ] | |
} | |||
], | |||
"prompt_number": 5 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"But after we import dill, magic happens" | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"import dill" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 6 | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"pickle.dumps(closed)[:64] + '...'" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"metadata": {}, | |||
"output_type": "pyout", | |||
"prompt_number": 7, | |||
"text": [ | |||
"\"cdill.dill\\n_load_type\\np0\\n(S'FunctionType'\\np1\\ntp2\\nRp3\\n(cdill.dill...\"" | |||
] | |||
} | |||
], | |||
"prompt_number": 7 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"So from now on, pretty much everything is pickleable." | |||
] | |||
}, | |||
{ | |||
"cell_type": "heading", | |||
"level": 2, | |||
"metadata": {}, | |||
"source": [ | |||
"Now use this in IPython.parallel" | |||
] | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"As usual, we start by creating our Client and View" | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"from IPython import parallel\n", | |||
"rc = parallel.Client()\n", | |||
"view = rc.load_balanced_view()" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 8 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"Now let's try sending our function with a closure:" | |||
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"view.apply_sync(closed, 3)" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"ename": "ValueError", | |||
"evalue": "Sorry, cannot pickle code objects with closures", | |||
"output_type": "pyerr", | |||
"traceback": [ | |||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", | |||
"\u001b[1;32m<ipython-input-9-23a646829fdc>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mview\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mapply_sync\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mclosed\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", | |||
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36mapply_sync\u001b[1;34m(self, f, *args, **kwargs)\u001b[0m\n", | |||
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36mspin_after\u001b[1;34m(f, self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 73\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mspin_after\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 74\u001b[0m \u001b[1;34m\"\"\"call spin after the method.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 75\u001b[1;33m \u001b[0mret\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 76\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mspin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 77\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mret\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |||
MinRK
|
r13878 | "\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36mapply_sync\u001b[1;34m(self, f, *args, **kwargs)\u001b[0m\n\u001b[0;32m 245\u001b[0m \u001b[0mreturning\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mresult\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 246\u001b[0m \"\"\"\n\u001b[1;32m--> 247\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_really_apply\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mblock\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 248\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 249\u001b[0m \u001b[1;31m#----------------------------------------------------------------\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |
MinRK
|
r13638 | "\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36m_really_apply\u001b[1;34m(self, f, args, kwargs, block, track, after, follow, timeout, targets, retries)\u001b[0m\n", | |
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36msync_results\u001b[1;34m(f, self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 64\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_in_sync_results\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mTrue\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 65\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 66\u001b[1;33m \u001b[0mret\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 67\u001b[0m \u001b[1;32mfinally\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 68\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_in_sync_results\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mFalse\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |||
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36m_really_apply\u001b[1;34m(self, f, args, kwargs, block, track, after, follow, timeout, targets, retries)\u001b[0m\n", | |||
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36msave_ids\u001b[1;34m(f, self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 49\u001b[0m \u001b[0mn_previous\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclient\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 50\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 51\u001b[1;33m \u001b[0mret\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 52\u001b[0m \u001b[1;32mfinally\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 53\u001b[0m \u001b[0mnmsgs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclient\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m-\u001b[0m \u001b[0mn_previous\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |||
MinRK
|
r13878 | "\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/view.pyc\u001b[0m in \u001b[0;36m_really_apply\u001b[1;34m(self, f, args, kwargs, block, track, after, follow, timeout, targets, retries)\u001b[0m\n\u001b[0;32m 1049\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1050\u001b[0m msg = self.client.send_apply_request(self._socket, f, args, kwargs, track=track,\n\u001b[1;32m-> 1051\u001b[1;33m metadata=metadata)\n\u001b[0m\u001b[0;32m 1052\u001b[0m \u001b[0mtracker\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mNone\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mtrack\u001b[0m \u001b[1;32mis\u001b[0m \u001b[0mFalse\u001b[0m \u001b[1;32melse\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'tracker'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1053\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", | |
MinRK
|
r13638 | "\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/parallel/client/client.pyc\u001b[0m in \u001b[0;36msend_apply_request\u001b[1;34m(self, socket, f, args, kwargs, metadata, track, ident)\u001b[0m\n\u001b[0;32m 1252\u001b[0m bufs = serialize.pack_apply_message(f, args, kwargs,\n\u001b[0;32m 1253\u001b[0m \u001b[0mbuffer_threshold\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbuffer_threshold\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1254\u001b[1;33m \u001b[0mitem_threshold\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msession\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitem_threshold\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1255\u001b[0m )\n\u001b[0;32m 1256\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", | |
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/kernel/zmq/serialize.pyc\u001b[0m in \u001b[0;36mpack_apply_message\u001b[1;34m(f, args, kwargs, buffer_threshold, item_threshold)\u001b[0m\n\u001b[0;32m 163\u001b[0m \u001b[0minfo\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnargs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnarg_bufs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0marg_bufs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkw_keys\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mkw_keys\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 164\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 165\u001b[1;33m \u001b[0mmsg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mpickle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcan\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 166\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpickle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0minfo\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 167\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0marg_bufs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |||
"\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/utils/codeutil.pyc\u001b[0m in \u001b[0;36mreduce_code\u001b[1;34m(co)\u001b[0m\n\u001b[0;32m 36\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mreduce_code\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mco\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 37\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mco\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_freevars\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mco\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_cellvars\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 38\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Sorry, cannot pickle code objects with closures\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 39\u001b[0m args = [co.co_argcount, co.co_nlocals, co.co_stacksize,\n\u001b[0;32m 40\u001b[0m \u001b[0mco\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_flags\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mco\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_code\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mco\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_consts\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mco\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_names\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", | |||
"\u001b[1;31mValueError\u001b[0m: Sorry, cannot pickle code objects with closures" | |||
] | |||
} | |||
], | |||
"prompt_number": 9 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"Oops, no dice. For IPython to work with dill,\n", | |||
MinRK
|
r13878 | "there are one or two more steps. IPython will do these for you if you call `DirectView.use_dill`:" | |
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
MinRK
|
r13878 | "rc[:].use_dill()" | |
MinRK
|
r13638 | ], | |
"language": "python", | |||
"metadata": {}, | |||
MinRK
|
r13878 | "outputs": [ | |
{ | |||
"metadata": {}, | |||
"output_type": "pyout", | |||
"prompt_number": 10, | |||
"text": [ | |||
"<AsyncResult: use_dill>" | |||
] | |||
} | |||
], | |||
MinRK
|
r13638 | "prompt_number": 10 | |
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
MinRK
|
r13878 | "This is equivalent to\n", | |
"\n", | |||
"```python\n", | |||
"from IPython.utils.pickleutil import use_dill\n", | |||
"use_dill()\n", | |||
"rc[:].apply(use_dill)\n", | |||
"```" | |||
] | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
MinRK
|
r13638 | "Now let's try again" | |
] | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"view.apply_sync(closed, 3)" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"metadata": {}, | |||
"output_type": "pyout", | |||
"prompt_number": 11, | |||
"text": [ | |||
"15" | |||
] | |||
} | |||
], | |||
"prompt_number": 11 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"Yay! Now we can use dill to allow IPython.parallel to send anything.\n", | |||
"\n", | |||
"And that's it! We can send closures and other previously non-pickleables to our engines.\n", | |||
"\n", | |||
MinRK
|
r13878 | "Let's give it a try now:" | |
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
MinRK
|
r13878 | "remote_closure = view.apply_sync(make_closure, 4)\n", | |
"remote_closure(5)" | |||
MinRK
|
r13638 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
MinRK
|
r13878 | "metadata": {}, | |
"output_type": "pyout", | |||
"prompt_number": 12, | |||
"text": [ | |||
"20" | |||
MinRK
|
r13638 | ] | |
} | |||
], | |||
"prompt_number": 12 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
MinRK
|
r13878 | "But wait, there's more!\n", | |
MinRK
|
r13638 | "\n", | |
MinRK
|
r13878 | "At this point, we can send/recv all kinds of stuff" | |
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
MinRK
|
r13878 | "def outer(a):\n", | |
" def inner(b):\n", | |||
" def inner_again(c):\n", | |||
" return c * b * a\n", | |||
" return inner_again\n", | |||
" return inner" | |||
MinRK
|
r13638 | ], | |
"language": "python", | |||
"metadata": {}, | |||
MinRK
|
r13878 | "outputs": [], | |
MinRK
|
r13638 | "prompt_number": 13 | |
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
MinRK
|
r13878 | "So outer returns a function with a closure, which returns a function with a closure.\n", | |
MinRK
|
r13638 | "\n", | |
MinRK
|
r13878 | "Now, we can resolve the first closure on the engine, the second here, and the third on a different engine,\n", | |
"after passing through a lambda we define here and call there, just for good measure." | |||
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
MinRK
|
r13878 | "cell_type": "code", | |
"collapsed": false, | |||
"input": [ | |||
"view.apply_sync(lambda f: f(3),view.apply_sync(outer, 1)(2))" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"metadata": {}, | |||
"output_type": "pyout", | |||
"prompt_number": 14, | |||
"text": [ | |||
"6" | |||
] | |||
} | |||
], | |||
"prompt_number": 14 | |||
}, | |||
{ | |||
MinRK
|
r13638 | "cell_type": "markdown", | |
"metadata": {}, | |||
"source": [ | |||
MinRK
|
r13878 | "And for good measure, let's test that normal execution still works:" | |
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
MinRK
|
r13878 | "%px foo = 5\n", | |
"\n", | |||
"print(rc[:]['foo'])\n", | |||
"rc[:]['bar'] = lambda : 2 * foo\n", | |||
"rc[:].apply_sync(parallel.Reference('bar'))" | |||
MinRK
|
r13638 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
MinRK
|
r13878 | "output_type": "stream", | |
"stream": "stdout", | |||
"text": [ | |||
"[5, 5, 5, 5, 5, 5, 5, 5]\n" | |||
] | |||
}, | |||
{ | |||
MinRK
|
r13638 | "metadata": {}, | |
"output_type": "pyout", | |||
MinRK
|
r13878 | "prompt_number": 15, | |
MinRK
|
r13638 | "text": [ | |
MinRK
|
r13878 | "[10, 10, 10, 10, 10, 10, 10, 10]" | |
MinRK
|
r13638 | ] | |
} | |||
], | |||
MinRK
|
r13878 | "prompt_number": 15 | |
MinRK
|
r13638 | }, | |
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
MinRK
|
r13878 | "And test that the `@interactive` decorator works" | |
MinRK
|
r13638 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
MinRK
|
r13878 | "%%file testdill.py\n", | |
"from IPython.parallel import interactive\n", | |||
"\n", | |||
"@interactive\n", | |||
"class C(object):\n", | |||
" a = 5\n", | |||
"\n", | |||
"@interactive\n", | |||
"class D(C):\n", | |||
" b = 10\n", | |||
"\n", | |||
"@interactive\n", | |||
"def foo(a):\n", | |||
" return a * b\n" | |||
], | |||
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"output_type": "stream", | |||
"stream": "stdout", | |||
"text": [ | |||
"Overwriting testdill.py\n" | |||
] | |||
} | |||
], | |||
"prompt_number": 16 | |||
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"import testdill" | |||
MinRK
|
r13638 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
MinRK
|
r13878 | "prompt_number": 17 | |
MinRK
|
r13638 | }, | |
{ | |||
MinRK
|
r13878 | "cell_type": "code", | |
"collapsed": false, | |||
"input": [ | |||
"v = rc[-1]\n", | |||
"v['D'] = testdill.D\n", | |||
"d = v.apply_sync(lambda : D())\n", | |||
"print d.a, d.b" | |||
], | |||
"language": "python", | |||
MinRK
|
r13638 | "metadata": {}, | |
MinRK
|
r13878 | "outputs": [ | |
{ | |||
"output_type": "stream", | |||
"stream": "stdout", | |||
"text": [ | |||
"5 10\n" | |||
] | |||
} | |||
], | |||
"prompt_number": 18 | |||
MinRK
|
r13638 | }, | |
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
MinRK
|
r13878 | "v['b'] = 10\n", | |
"v.apply_sync(testdill.foo, 5)" | |||
MinRK
|
r13638 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
"metadata": {}, | |||
"output_type": "pyout", | |||
MinRK
|
r13878 | "prompt_number": 19, | |
MinRK
|
r13638 | "text": [ | |
MinRK
|
r13878 | "50" | |
MinRK
|
r13638 | ] | |
} | |||
], | |||
MinRK
|
r13878 | "prompt_number": 19 | |
MinRK
|
r13638 | } | |
], | |||
"metadata": {} | |||
} | |||
] | |||
} |