##// END OF EJS Templates
update parallel magics docstring
MinRK -
Show More
@@ -1,411 +1,411 b''
1 1 # encoding: utf-8
2 2 """
3 3 =============
4 4 parallelmagic
5 5 =============
6 6
7 7 Magic command interface for interactive parallel work.
8 8
9 9 Usage
10 10 =====
11 11
12 12 ``%autopx``
13 13
14 14 {AUTOPX_DOC}
15 15
16 16 ``%px``
17 17
18 18 {PX_DOC}
19 19
20 20 ``%pxresult``
21 21
22 22 {RESULT_DOC}
23 23
24 24 ``%pxconfig``
25 25
26 26 {CONFIG_DOC}
27 27
28 28 """
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Copyright (C) 2008 The IPython Development Team
32 32 #
33 33 # Distributed under the terms of the BSD License. The full license is in
34 34 # the file COPYING, distributed as part of this software.
35 35 #-----------------------------------------------------------------------------
36 36
37 37 #-----------------------------------------------------------------------------
38 38 # Imports
39 39 #-----------------------------------------------------------------------------
40 40
41 41 import ast
42 42 import re
43 43
44 44 from IPython.core.error import UsageError
45 45 from IPython.core.magic import Magics
46 46 from IPython.core import magic_arguments
47 47 from IPython.testing.skipdoctest import skip_doctest
48 48
49 49 #-----------------------------------------------------------------------------
50 50 # Definitions of magic functions for use with IPython
51 51 #-----------------------------------------------------------------------------
52 52
53 53
54 54 NO_LAST_RESULT = "%pxresult recalls last %px result, which has not yet been used."
55 55
56 56 def exec_args(f):
57 57 """decorator for adding block/targets args for execution
58 58
59 59 applied to %pxconfig and %%px
60 60 """
61 61 args = [
62 62 magic_arguments.argument('-b', '--block', action="store_const",
63 63 const=True, dest='block',
64 64 help="use blocking (sync) execution"
65 65 ),
66 66 magic_arguments.argument('-a', '--noblock', action="store_const",
67 67 const=False, dest='block',
68 68 help="use non-blocking (async) execution"
69 69 ),
70 70 magic_arguments.argument('-t', '--targets', type=str,
71 71 help="specify the targets on which to execute"
72 72 ),
73 73 ]
74 74 for a in args:
75 75 f = a(f)
76 76 return f
77 77
78 78 def output_args(f):
79 79 """decorator for output-formatting args
80 80
81 81 applied to %pxresult and %%px
82 82 """
83 83 args = [
84 84 magic_arguments.argument('-r', action="store_const", dest='groupby',
85 85 const='order',
86 86 help="collate outputs in order (same as group-outputs=order)"
87 87 ),
88 88 magic_arguments.argument('-e', action="store_const", dest='groupby',
89 89 const='engine',
90 90 help="group outputs by engine (same as group-outputs=engine)"
91 91 ),
92 92 magic_arguments.argument('--group-outputs', dest='groupby', type=str,
93 93 choices=['engine', 'order', 'type'], default='type',
94 94 help="""Group the outputs in a particular way.
95 95
96 96 Choices are:
97 97
98 98 type: group outputs of all engines by type (stdout, stderr, displaypub, etc.).
99 99
100 100 engine: display all output for each engine together.
101 101
102 102 order: like type, but individual displaypub output from each engine is collated.
103 103 For example, if multiple plots are generated by each engine, the first
104 104 figure of each engine will be displayed, then the second of each, etc.
105 105 """
106 106 ),
107 107 magic_arguments.argument('-o', '--out', dest='save_name', type=str,
108 108 help="""store the AsyncResult object for this computation
109 109 in the global namespace under this name.
110 110 """
111 111 ),
112 112 ]
113 113 for a in args:
114 114 f = a(f)
115 115 return f
116 116
117 117 class ParallelMagics(Magics):
118 118 """A set of magics useful when controlling a parallel IPython cluster.
119 119 """
120 120
121 121 # magic-related
122 122 magics = None
123 123 registered = True
124 124
125 125 # suffix for magics
126 126 suffix = ''
127 127 # A flag showing if autopx is activated or not
128 128 _autopx = False
129 129 # the current view used by the magics:
130 130 view = None
131 131 # last result cache for %pxresult
132 132 last_result = None
133 133
134 134 def __init__(self, shell, view, suffix=''):
135 135 self.view = view
136 136 self.suffix = suffix
137 137
138 138 # register magics
139 139 self.magics = dict(cell={},line={})
140 140 line_magics = self.magics['line']
141 141
142 142 px = 'px' + suffix
143 143 if not suffix:
144 144 # keep %result for legacy compatibility
145 145 line_magics['result'] = self.result
146 146
147 147 line_magics['pxresult' + suffix] = self.result
148 148 line_magics[px] = self.px
149 149 line_magics['pxconfig' + suffix] = self.pxconfig
150 150 line_magics['auto' + px] = self.autopx
151 151
152 152 self.magics['cell'][px] = self.cell_px
153 153
154 154 super(ParallelMagics, self).__init__(shell=shell)
155 155
156 156 def _eval_target_str(self, ts):
157 157 if ':' in ts:
158 158 targets = eval("self.view.client.ids[%s]" % ts)
159 159 elif 'all' in ts:
160 160 targets = 'all'
161 161 else:
162 162 targets = eval(ts)
163 163 return targets
164 164
165 165 @magic_arguments.magic_arguments()
166 166 @exec_args
167 167 def pxconfig(self, line):
168 168 """configure default targets/blocking for %px magics"""
169 169 args = magic_arguments.parse_argstring(self.pxconfig, line)
170 170 if args.targets:
171 171 self.view.targets = self._eval_target_str(args.targets)
172 172 if args.block is not None:
173 173 self.view.block = args.block
174 174
175 175 @magic_arguments.magic_arguments()
176 176 @output_args
177 177 @skip_doctest
178 178 def result(self, line=''):
179 179 """Print the result of the last asynchronous %px command.
180 180
181 181 This lets you recall the results of %px computations after
182 182 asynchronous submission (block=False).
183 183
184 184 Examples
185 185 --------
186 186 ::
187 187
188 188 In [23]: %px os.getpid()
189 189 Async parallel execution on engine(s): all
190 190
191 191 In [24]: %pxresult
192 [ 8] Out[10]: 60920
193 [ 9] Out[10]: 60921
194 [10] Out[10]: 60922
195 [11] Out[10]: 60923
192 Out[8:10]: 60920
193 Out[9:10]: 60921
194 Out[10:10]: 60922
195 Out[11:10]: 60923
196 196 """
197 197 args = magic_arguments.parse_argstring(self.result, line)
198 198
199 199 if self.last_result is None:
200 200 raise UsageError(NO_LAST_RESULT)
201 201
202 202 self.last_result.get()
203 203 self.last_result.display_outputs(groupby=args.groupby)
204 204
205 205 @skip_doctest
206 206 def px(self, line=''):
207 207 """Executes the given python command in parallel.
208 208
209 209 Examples
210 210 --------
211 211 ::
212 212
213 213 In [24]: %px a = os.getpid()
214 214 Parallel execution on engine(s): all
215 215
216 216 In [25]: %px print a
217 217 [stdout:0] 1234
218 218 [stdout:1] 1235
219 219 [stdout:2] 1236
220 220 [stdout:3] 1237
221 221 """
222 222 return self.parallel_execute(line)
223 223
224 224 def parallel_execute(self, cell, block=None, groupby='type', save_name=None):
225 225 """implementation used by %px and %%parallel"""
226 226
227 227 # defaults:
228 228 block = self.view.block if block is None else block
229 229
230 230 base = "Parallel" if block else "Async parallel"
231 231
232 232 targets = self.view.targets
233 233 if isinstance(targets, list) and len(targets) > 10:
234 234 str_targets = str(targets[:4])[:-1] + ', ..., ' + str(targets[-4:])[1:]
235 235 else:
236 236 str_targets = str(targets)
237 237 print base + " execution on engine(s): %s" % str_targets
238 238
239 239 result = self.view.execute(cell, silent=False, block=False)
240 240 self.last_result = result
241 241
242 242 if save_name:
243 243 self.shell.user_ns[save_name] = result
244 244
245 245 if block:
246 246 result.get()
247 247 result.display_outputs(groupby)
248 248 else:
249 249 # return AsyncResult only on non-blocking submission
250 250 return result
251 251
252 252 @magic_arguments.magic_arguments()
253 253 @exec_args
254 254 @output_args
255 255 @skip_doctest
256 256 def cell_px(self, line='', cell=None):
257 257 """Executes the cell in parallel.
258 258
259 259 Examples
260 260 --------
261 261 ::
262 262
263 263 In [24]: %%px --noblock
264 264 ....: a = os.getpid()
265 265 Async parallel execution on engine(s): all
266 266
267 267 In [25]: %%px
268 268 ....: print a
269 269 [stdout:0] 1234
270 270 [stdout:1] 1235
271 271 [stdout:2] 1236
272 272 [stdout:3] 1237
273 273 """
274 274
275 275 args = magic_arguments.parse_argstring(self.cell_px, line)
276 276
277 277 if args.targets:
278 278 save_targets = self.view.targets
279 279 self.view.targets = self._eval_target_str(args.targets)
280 280 try:
281 281 return self.parallel_execute(cell, block=args.block,
282 282 groupby=args.groupby,
283 283 save_name=args.save_name,
284 284 )
285 285 finally:
286 286 if args.targets:
287 287 self.view.targets = save_targets
288 288
289 289 @skip_doctest
290 290 def autopx(self, line=''):
291 291 """Toggles auto parallel mode.
292 292
293 293 Once this is called, all commands typed at the command line are send to
294 294 the engines to be executed in parallel. To control which engine are
295 295 used, the ``targets`` attribute of the view before
296 296 entering ``%autopx`` mode.
297 297
298 298
299 299 Then you can do the following::
300 300
301 301 In [25]: %autopx
302 302 %autopx to enabled
303 303
304 304 In [26]: a = 10
305 305 Parallel execution on engine(s): [0,1,2,3]
306 306 In [27]: print a
307 307 Parallel execution on engine(s): [0,1,2,3]
308 308 [stdout:0] 10
309 309 [stdout:1] 10
310 310 [stdout:2] 10
311 311 [stdout:3] 10
312 312
313 313
314 314 In [27]: %autopx
315 315 %autopx disabled
316 316 """
317 317 if self._autopx:
318 318 self._disable_autopx()
319 319 else:
320 320 self._enable_autopx()
321 321
322 322 def _enable_autopx(self):
323 323 """Enable %autopx mode by saving the original run_cell and installing
324 324 pxrun_cell.
325 325 """
326 326 # override run_cell
327 327 self._original_run_cell = self.shell.run_cell
328 328 self.shell.run_cell = self.pxrun_cell
329 329
330 330 self._autopx = True
331 331 print "%autopx enabled"
332 332
333 333 def _disable_autopx(self):
334 334 """Disable %autopx by restoring the original InteractiveShell.run_cell.
335 335 """
336 336 if self._autopx:
337 337 self.shell.run_cell = self._original_run_cell
338 338 self._autopx = False
339 339 print "%autopx disabled"
340 340
341 341 def pxrun_cell(self, raw_cell, store_history=False, silent=False):
342 342 """drop-in replacement for InteractiveShell.run_cell.
343 343
344 344 This executes code remotely, instead of in the local namespace.
345 345
346 346 See InteractiveShell.run_cell for details.
347 347 """
348 348
349 349 if (not raw_cell) or raw_cell.isspace():
350 350 return
351 351
352 352 ipself = self.shell
353 353
354 354 with ipself.builtin_trap:
355 355 cell = ipself.prefilter_manager.prefilter_lines(raw_cell)
356 356
357 357 # Store raw and processed history
358 358 if store_history:
359 359 ipself.history_manager.store_inputs(ipself.execution_count,
360 360 cell, raw_cell)
361 361
362 362 # ipself.logger.log(cell, raw_cell)
363 363
364 364 cell_name = ipself.compile.cache(cell, ipself.execution_count)
365 365
366 366 try:
367 367 ast.parse(cell, filename=cell_name)
368 368 except (OverflowError, SyntaxError, ValueError, TypeError,
369 369 MemoryError):
370 370 # Case 1
371 371 ipself.showsyntaxerror()
372 372 ipself.execution_count += 1
373 373 return None
374 374 except NameError:
375 375 # ignore name errors, because we don't know the remote keys
376 376 pass
377 377
378 378 if store_history:
379 379 # Write output to the database. Does nothing unless
380 380 # history output logging is enabled.
381 381 ipself.history_manager.store_output(ipself.execution_count)
382 382 # Each cell is a *single* input, regardless of how many lines it has
383 383 ipself.execution_count += 1
384 384 if re.search(r'get_ipython\(\)\.magic\(u?["\']%?autopx', cell):
385 385 self._disable_autopx()
386 386 return False
387 387 else:
388 388 try:
389 389 result = self.view.execute(cell, silent=False, block=False)
390 390 except:
391 391 ipself.showtraceback()
392 392 return True
393 393 else:
394 394 if self.view.block:
395 395 try:
396 396 result.get()
397 397 except:
398 398 self.shell.showtraceback()
399 399 return True
400 400 else:
401 401 with ipself.builtin_trap:
402 402 result.display_outputs()
403 403 return False
404 404
405 405
406 406 __doc__ = __doc__.format(
407 407 AUTOPX_DOC = ' '*8 + ParallelMagics.autopx.__doc__,
408 408 PX_DOC = ' '*8 + ParallelMagics.px.__doc__,
409 409 RESULT_DOC = ' '*8 + ParallelMagics.result.__doc__,
410 410 CONFIG_DOC = ' '*8 + ParallelMagics.pxconfig.__doc__,
411 411 )
General Comments 0
You need to be logged in to leave comments. Login now