##// END OF EJS Templates
Merge pull request #4552 from minrk/use_dill...
Min RK -
r13728:818f778e merge
parent child Browse files
Show More
@@ -0,0 +1,7 b''
1 Using dill to expand serialization support
2 ------------------------------------------
3
4 adds :func:`~IPython.utils.pickleutil.use_dill` for allowing
5 dill to extend serialization support in :mod:`IPython.parallel` (closures, etc.).
6 Also adds :meth:`DirectView.use_dill` convenience method for enabling dill
7 locally and on all engines with one call.
@@ -0,0 +1,463 b''
1 {
2 "metadata": {
3 "gist_id": "5241793",
4 "name": ""
5 },
6 "nbformat": 3,
7 "nbformat_minor": 0,
8 "worksheets": [
9 {
10 "cells": [
11 {
12 "cell_type": "heading",
13 "level": 1,
14 "metadata": {},
15 "source": [
16 "Using dill to pickle anything"
17 ]
18 },
19 {
20 "cell_type": "markdown",
21 "metadata": {},
22 "source": [
23 "IPython.parallel doesn't do much in the way of serialization.\n",
24 "It has custom zero-copy handling of numpy arrays,\n",
25 "but other than that, it doesn't do anything other than the bare minimum to make basic interactively defined functions and classes sendable.\n",
26 "\n",
27 "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",
28 "\n",
29 "To install dill:\n",
30 " \n",
31 " pip install dill"
32 ]
33 },
34 {
35 "cell_type": "markdown",
36 "metadata": {},
37 "source": [
38 "First, as always, we create a task function, this time with a closure"
39 ]
40 },
41 {
42 "cell_type": "code",
43 "collapsed": false,
44 "input": [
45 "def make_closure(a):\n",
46 " \"\"\"make a function with a closure, and return it\"\"\"\n",
47 " def has_closure(b):\n",
48 " return a * b\n",
49 " return has_closure"
50 ],
51 "language": "python",
52 "metadata": {},
53 "outputs": [],
54 "prompt_number": 1
55 },
56 {
57 "cell_type": "code",
58 "collapsed": false,
59 "input": [
60 "closed = make_closure(5)"
61 ],
62 "language": "python",
63 "metadata": {},
64 "outputs": [],
65 "prompt_number": 2
66 },
67 {
68 "cell_type": "code",
69 "collapsed": false,
70 "input": [
71 "closed(2)"
72 ],
73 "language": "python",
74 "metadata": {},
75 "outputs": [
76 {
77 "metadata": {},
78 "output_type": "pyout",
79 "prompt_number": 3,
80 "text": [
81 "10"
82 ]
83 }
84 ],
85 "prompt_number": 3
86 },
87 {
88 "cell_type": "code",
89 "collapsed": false,
90 "input": [
91 "import pickle"
92 ],
93 "language": "python",
94 "metadata": {},
95 "outputs": [],
96 "prompt_number": 4
97 },
98 {
99 "cell_type": "markdown",
100 "metadata": {},
101 "source": [
102 "Without help, pickle can't deal with closures"
103 ]
104 },
105 {
106 "cell_type": "code",
107 "collapsed": false,
108 "input": [
109 "pickle.dumps(closed)"
110 ],
111 "language": "python",
112 "metadata": {},
113 "outputs": [
114 {
115 "ename": "PicklingError",
116 "evalue": "Can't pickle <function has_closure at 0x10d2552a8>: it's not found as __main__.has_closure",
117 "output_type": "pyerr",
118 "traceback": [
119 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mPicklingError\u001b[0m Traceback (most recent call last)",
120 "\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",
121 "\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",
122 "\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",
123 "\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",
124 "\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",
125 "\u001b[1;31mPicklingError\u001b[0m: Can't pickle <function has_closure at 0x10d2552a8>: it's not found as __main__.has_closure"
126 ]
127 }
128 ],
129 "prompt_number": 5
130 },
131 {
132 "cell_type": "markdown",
133 "metadata": {},
134 "source": [
135 "But after we import dill, magic happens"
136 ]
137 },
138 {
139 "cell_type": "code",
140 "collapsed": false,
141 "input": [
142 "import dill"
143 ],
144 "language": "python",
145 "metadata": {},
146 "outputs": [],
147 "prompt_number": 6
148 },
149 {
150 "cell_type": "code",
151 "collapsed": false,
152 "input": [
153 "pickle.dumps(closed)[:64] + '...'"
154 ],
155 "language": "python",
156 "metadata": {},
157 "outputs": [
158 {
159 "metadata": {},
160 "output_type": "pyout",
161 "prompt_number": 7,
162 "text": [
163 "\"cdill.dill\\n_load_type\\np0\\n(S'FunctionType'\\np1\\ntp2\\nRp3\\n(cdill.dill...\""
164 ]
165 }
166 ],
167 "prompt_number": 7
168 },
169 {
170 "cell_type": "markdown",
171 "metadata": {},
172 "source": [
173 "So from now on, pretty much everything is pickleable."
174 ]
175 },
176 {
177 "cell_type": "heading",
178 "level": 2,
179 "metadata": {},
180 "source": [
181 "Now use this in IPython.parallel"
182 ]
183 },
184 {
185 "cell_type": "markdown",
186 "metadata": {},
187 "source": [
188 "As usual, we start by creating our Client and View"
189 ]
190 },
191 {
192 "cell_type": "code",
193 "collapsed": false,
194 "input": [
195 "from IPython import parallel\n",
196 "rc = parallel.Client()\n",
197 "view = rc.load_balanced_view()"
198 ],
199 "language": "python",
200 "metadata": {},
201 "outputs": [],
202 "prompt_number": 8
203 },
204 {
205 "cell_type": "markdown",
206 "metadata": {},
207 "source": [
208 "Now let's try sending our function with a closure:"
209 ]
210 },
211 {
212 "cell_type": "code",
213 "collapsed": false,
214 "input": [
215 "view.apply_sync(closed, 3)"
216 ],
217 "language": "python",
218 "metadata": {},
219 "outputs": [
220 {
221 "ename": "ValueError",
222 "evalue": "Sorry, cannot pickle code objects with closures",
223 "output_type": "pyerr",
224 "traceback": [
225 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
226 "\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",
227 "\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",
228 "\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",
229 "\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 248\u001b[0m \u001b[0mreturns\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mactual\u001b[0m \u001b[0mresult\u001b[0m \u001b[0mof\u001b[0m \u001b[0mf\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[0;32m 249\u001b[0m \"\"\"\n\u001b[1;32m--> 250\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 251\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 252\u001b[0m \u001b[1;31m#----------------------------------------------------------------\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
230 "\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",
231 "\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",
232 "\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",
233 "\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",
234 "\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 1053\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1054\u001b[0m msg = self.client.send_apply_request(self._socket, f, args, kwargs, track=track,\n\u001b[1;32m-> 1055\u001b[1;33m metadata=metadata)\n\u001b[0m\u001b[0;32m 1056\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 1057\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
235 "\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",
236 "\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",
237 "\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",
238 "\u001b[1;31mValueError\u001b[0m: Sorry, cannot pickle code objects with closures"
239 ]
240 }
241 ],
242 "prompt_number": 9
243 },
244 {
245 "cell_type": "markdown",
246 "metadata": {},
247 "source": [
248 "Oops, no dice. For IPython to work with dill,\n",
249 "there are one or two more steps. IPython will do these for you if you call `pickleutil.use_dill`:"
250 ]
251 },
252 {
253 "cell_type": "code",
254 "collapsed": false,
255 "input": [
256 "from IPython.utils import pickleutil\n",
257 "pickleutil.use_dill()"
258 ],
259 "language": "python",
260 "metadata": {},
261 "outputs": [],
262 "prompt_number": 10
263 },
264 {
265 "cell_type": "markdown",
266 "metadata": {},
267 "source": [
268 "Now let's try again"
269 ]
270 },
271 {
272 "cell_type": "code",
273 "collapsed": false,
274 "input": [
275 "view.apply_sync(closed, 3)"
276 ],
277 "language": "python",
278 "metadata": {},
279 "outputs": [
280 {
281 "metadata": {},
282 "output_type": "pyout",
283 "prompt_number": 11,
284 "text": [
285 "15"
286 ]
287 }
288 ],
289 "prompt_number": 11
290 },
291 {
292 "cell_type": "markdown",
293 "metadata": {},
294 "source": [
295 "Yay! Now we can use dill to allow IPython.parallel to send anything.\n",
296 "\n",
297 "And that's it! We can send closures and other previously non-pickleables to our engines.\n",
298 "\n",
299 "But wait, there's more!"
300 ]
301 },
302 {
303 "cell_type": "code",
304 "collapsed": false,
305 "input": [
306 "view.apply_sync(make_closure, 2)"
307 ],
308 "language": "python",
309 "metadata": {},
310 "outputs": [
311 {
312 "ename": "RemoteError",
313 "evalue": "ValueError(Sorry, cannot pickle code objects with closures)",
314 "output_type": "pyerr",
315 "traceback": [
316 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
317 "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)\u001b[1;32m/Users/minrk/dev/ip/mine/IPython/kernel/zmq/serialize.pyc\u001b[0m in \u001b[0;36mserialize_object\u001b[1;34m(obj, buffer_threshold, item_threshold)\u001b[0m",
318 "\u001b[0;32m 100\u001b[0m \u001b[0mbuffers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0m_extract_buffers\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbuffer_threshold\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m",
319 "\u001b[0;32m 101\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m",
320 "\u001b[1;32m--> 102\u001b[1;33m \u001b[0mbuffers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minsert\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0\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[0mcobj\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",
321 "\u001b[0m\u001b[0;32m 103\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mbuffers\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m",
322 "\u001b[0;32m 104\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m",
323 "\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",
324 "\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",
325 "\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",
326 "\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",
327 "\u001b[0m\u001b[0;32m 39\u001b[0m args = [co.co_argcount, co.co_nlocals, co.co_stacksize,",
328 "\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",
329 "\u001b[1;31mValueError\u001b[0m: Sorry, cannot pickle code objects with closures"
330 ]
331 }
332 ],
333 "prompt_number": 12
334 },
335 {
336 "cell_type": "markdown",
337 "metadata": {},
338 "source": [
339 "If we want dill support for objects coming *from* the engines,\n",
340 "then we need to call `use_dill()` there as well.\n",
341 "\n",
342 "`DirectView` objects have a method to call `use_dill` locally and on every engine:"
343 ]
344 },
345 {
346 "cell_type": "code",
347 "collapsed": false,
348 "input": [
349 "rc[:].use_dill()"
350 ],
351 "language": "python",
352 "metadata": {},
353 "outputs": [
354 {
355 "metadata": {},
356 "output_type": "pyout",
357 "prompt_number": 13,
358 "text": [
359 "<AsyncResult: use_dill>"
360 ]
361 }
362 ],
363 "prompt_number": 13
364 },
365 {
366 "cell_type": "markdown",
367 "metadata": {},
368 "source": [
369 "This is equivalent to\n",
370 "\n",
371 "```python\n",
372 "from IPython.utils.pickleutil import use_dill\n",
373 "use_dill()\n",
374 "rc[:].apply(use_dill)\n",
375 "```"
376 ]
377 },
378 {
379 "cell_type": "markdown",
380 "metadata": {},
381 "source": [
382 "Let's give it a try now:"
383 ]
384 },
385 {
386 "cell_type": "code",
387 "collapsed": false,
388 "input": [
389 "remote_closure = view.apply_sync(make_closure, 4)\n",
390 "remote_closure(5)"
391 ],
392 "language": "python",
393 "metadata": {},
394 "outputs": [
395 {
396 "metadata": {},
397 "output_type": "pyout",
398 "prompt_number": 14,
399 "text": [
400 "20"
401 ]
402 }
403 ],
404 "prompt_number": 14
405 },
406 {
407 "cell_type": "markdown",
408 "metadata": {},
409 "source": [
410 "At this point, we can send/recv all kinds of stuff"
411 ]
412 },
413 {
414 "cell_type": "code",
415 "collapsed": false,
416 "input": [
417 "def outer(a):\n",
418 " def inner(b):\n",
419 " def inner_again(c):\n",
420 " return c * b * a\n",
421 " return inner_again\n",
422 " return inner"
423 ],
424 "language": "python",
425 "metadata": {},
426 "outputs": [],
427 "prompt_number": 15
428 },
429 {
430 "cell_type": "markdown",
431 "metadata": {},
432 "source": [
433 "So outer returns a function with a closure, which returns a function with a closure.\n",
434 "\n",
435 "Now, we can resolve the first closure on the engine, the second here, and the third on a different engine,\n",
436 "after passing through a lambda we define here and call there, just for good measure."
437 ]
438 },
439 {
440 "cell_type": "code",
441 "collapsed": false,
442 "input": [
443 "view.apply_sync(lambda f: f(3),view.apply_sync(outer, 1)(2))"
444 ],
445 "language": "python",
446 "metadata": {},
447 "outputs": [
448 {
449 "metadata": {},
450 "output_type": "pyout",
451 "prompt_number": 16,
452 "text": [
453 "6"
454 ]
455 }
456 ],
457 "prompt_number": 16
458 }
459 ],
460 "metadata": {}
461 }
462 ]
463 } No newline at end of file
@@ -25,6 +25,7 b' from types import ModuleType'
25 import zmq
25 import zmq
26
26
27 from IPython.testing.skipdoctest import skip_doctest
27 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.utils import pickleutil
28 from IPython.utils.traitlets import (
29 from IPython.utils.traitlets import (
29 HasTraits, Any, Bool, List, Dict, Set, Instance, CFloat, Integer
30 HasTraits, Any, Bool, List, Dict, Set, Instance, CFloat, Integer
30 )
31 )
@@ -507,6 +508,16 b' class DirectView(View):'
507 for r in results:
508 for r in results:
508 # raise possible remote ImportErrors here
509 # raise possible remote ImportErrors here
509 r.get()
510 r.get()
511
512 def use_dill(self):
513 """Expand serialization support with dill
514
515 adds support for closures, etc.
516
517 This calls IPython.utils.pickleutil.use_dill() here and on each engine.
518 """
519 pickleutil.use_dill()
520 return self.apply(pickleutil.use_dill)
510
521
511
522
512 @sync_results
523 @sync_results
@@ -40,6 +40,36 b' else:'
40 class_type = (type, ClassType)
40 class_type = (type, ClassType)
41
41
42 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
43 # Functions
44 #-------------------------------------------------------------------------------
45
46
47 def use_dill():
48 """use dill to expand serialization support
49
50 adds support for object methods and closures to serialization.
51 """
52 # import dill causes most of the magic
53 import dill
54
55 # dill doesn't work with cPickle,
56 # tell the two relevant modules to use plain pickle
57
58 global pickle
59 pickle = dill
60
61 try:
62 from IPython.kernel.zmq import serialize
63 except ImportError:
64 pass
65 else:
66 serialize.pickle = dill
67
68 # disable special function handling, let dill take care of it
69 can_map.pop(FunctionType, None)
70
71
72 #-------------------------------------------------------------------------------
43 # Classes
73 # Classes
44 #-------------------------------------------------------------------------------
74 #-------------------------------------------------------------------------------
45
75
General Comments 0
You need to be logged in to leave comments. Login now