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