1 | #
|
---|
2 | # Package analogous to 'threading.py' but using processes
|
---|
3 | #
|
---|
4 | # multiprocessing/__init__.py
|
---|
5 | #
|
---|
6 | # This package is intended to duplicate the functionality (and much of
|
---|
7 | # the API) of threading.py but uses processes instead of threads. A
|
---|
8 | # subpackage 'multiprocessing.dummy' has the same API but is a simple
|
---|
9 | # wrapper for 'threading'.
|
---|
10 | #
|
---|
11 | # Try calling `multiprocessing.doc.main()` to read the html
|
---|
12 | # documentation in a webbrowser.
|
---|
13 | #
|
---|
14 | #
|
---|
15 | # Copyright (c) 2006-2008, R Oudkerk
|
---|
16 | # All rights reserved.
|
---|
17 | #
|
---|
18 | # Redistribution and use in source and binary forms, with or without
|
---|
19 | # modification, are permitted provided that the following conditions
|
---|
20 | # are met:
|
---|
21 | #
|
---|
22 | # 1. Redistributions of source code must retain the above copyright
|
---|
23 | # notice, this list of conditions and the following disclaimer.
|
---|
24 | # 2. Redistributions in binary form must reproduce the above copyright
|
---|
25 | # notice, this list of conditions and the following disclaimer in the
|
---|
26 | # documentation and/or other materials provided with the distribution.
|
---|
27 | # 3. Neither the name of author nor the names of any contributors may be
|
---|
28 | # used to endorse or promote products derived from this software
|
---|
29 | # without specific prior written permission.
|
---|
30 | #
|
---|
31 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
---|
32 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
33 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
34 | # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
---|
35 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
36 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
37 | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
38 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
39 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
---|
40 | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
41 | # SUCH DAMAGE.
|
---|
42 | #
|
---|
43 |
|
---|
44 | __version__ = '0.70a1'
|
---|
45 |
|
---|
46 | __all__ = [
|
---|
47 | 'Process', 'current_process', 'active_children', 'freeze_support',
|
---|
48 | 'Manager', 'Pipe', 'cpu_count', 'log_to_stderr', 'get_logger',
|
---|
49 | 'allow_connection_pickling', 'BufferTooShort', 'TimeoutError',
|
---|
50 | 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition',
|
---|
51 | 'Event', 'Queue', 'JoinableQueue', 'Pool', 'Value', 'Array',
|
---|
52 | 'RawValue', 'RawArray', 'SUBDEBUG', 'SUBWARNING',
|
---|
53 | ]
|
---|
54 |
|
---|
55 | __author__ = 'R. Oudkerk (r.m.oudkerk@gmail.com)'
|
---|
56 |
|
---|
57 | #
|
---|
58 | # Imports
|
---|
59 | #
|
---|
60 |
|
---|
61 | import os
|
---|
62 | import sys
|
---|
63 |
|
---|
64 | from multiprocessing.process import Process, current_process, active_children
|
---|
65 | from multiprocessing.util import SUBDEBUG, SUBWARNING
|
---|
66 |
|
---|
67 | #
|
---|
68 | # Exceptions
|
---|
69 | #
|
---|
70 |
|
---|
71 | class ProcessError(Exception):
|
---|
72 | pass
|
---|
73 |
|
---|
74 | class BufferTooShort(ProcessError):
|
---|
75 | pass
|
---|
76 |
|
---|
77 | class TimeoutError(ProcessError):
|
---|
78 | pass
|
---|
79 |
|
---|
80 | class AuthenticationError(ProcessError):
|
---|
81 | pass
|
---|
82 |
|
---|
83 | # This is down here because _multiprocessing uses BufferTooShort
|
---|
84 | import _multiprocessing
|
---|
85 |
|
---|
86 | #
|
---|
87 | # Definitions not depending on native semaphores
|
---|
88 | #
|
---|
89 |
|
---|
90 | def Manager():
|
---|
91 | '''
|
---|
92 | Returns a manager associated with a running server process
|
---|
93 |
|
---|
94 | The managers methods such as `Lock()`, `Condition()` and `Queue()`
|
---|
95 | can be used to create shared objects.
|
---|
96 | '''
|
---|
97 | from multiprocessing.managers import SyncManager
|
---|
98 | m = SyncManager()
|
---|
99 | m.start()
|
---|
100 | return m
|
---|
101 |
|
---|
102 | def Pipe(duplex=True):
|
---|
103 | '''
|
---|
104 | Returns two connection object connected by a pipe
|
---|
105 | '''
|
---|
106 | from multiprocessing.connection import Pipe
|
---|
107 | return Pipe(duplex)
|
---|
108 |
|
---|
109 | def cpu_count():
|
---|
110 | '''
|
---|
111 | Returns the number of CPUs in the system
|
---|
112 | '''
|
---|
113 | if sys.platform == 'win32':
|
---|
114 | try:
|
---|
115 | num = int(os.environ['NUMBER_OF_PROCESSORS'])
|
---|
116 | except (ValueError, KeyError):
|
---|
117 | num = 0
|
---|
118 | elif 'bsd' in sys.platform or sys.platform == 'darwin':
|
---|
119 | comm = '/sbin/sysctl -n hw.ncpu'
|
---|
120 | if sys.platform == 'darwin':
|
---|
121 | comm = '/usr' + comm
|
---|
122 | try:
|
---|
123 | with os.popen(comm) as p:
|
---|
124 | num = int(p.read())
|
---|
125 | except ValueError:
|
---|
126 | num = 0
|
---|
127 | else:
|
---|
128 | try:
|
---|
129 | num = 0
|
---|
130 | if os.name == 'os2':
|
---|
131 | try:
|
---|
132 | num = int(os.environ['NUMBER_OF_PROCESSORS'])
|
---|
133 | except (ValueError, KeyError):
|
---|
134 | num = 0
|
---|
135 | if num == 0:
|
---|
136 | num = os.sysconf('SC_NPROCESSORS_ONLN')
|
---|
137 | except (ValueError, OSError, AttributeError):
|
---|
138 | num = 0
|
---|
139 |
|
---|
140 | if num >= 1:
|
---|
141 | return num
|
---|
142 | else:
|
---|
143 | raise NotImplementedError('cannot determine number of cpus')
|
---|
144 |
|
---|
145 | def freeze_support():
|
---|
146 | '''
|
---|
147 | Check whether this is a fake forked process in a frozen executable.
|
---|
148 | If so then run code specified by commandline and exit.
|
---|
149 | '''
|
---|
150 | if sys.platform == 'win32' and getattr(sys, 'frozen', False):
|
---|
151 | from multiprocessing.forking import freeze_support
|
---|
152 | freeze_support()
|
---|
153 |
|
---|
154 | def get_logger():
|
---|
155 | '''
|
---|
156 | Return package logger -- if it does not already exist then it is created
|
---|
157 | '''
|
---|
158 | from multiprocessing.util import get_logger
|
---|
159 | return get_logger()
|
---|
160 |
|
---|
161 | def log_to_stderr(level=None):
|
---|
162 | '''
|
---|
163 | Turn on logging and add a handler which prints to stderr
|
---|
164 | '''
|
---|
165 | from multiprocessing.util import log_to_stderr
|
---|
166 | return log_to_stderr(level)
|
---|
167 |
|
---|
168 | def allow_connection_pickling():
|
---|
169 | '''
|
---|
170 | Install support for sending connections and sockets between processes
|
---|
171 | '''
|
---|
172 | from multiprocessing import reduction
|
---|
173 |
|
---|
174 | #
|
---|
175 | # Definitions depending on native semaphores
|
---|
176 | #
|
---|
177 |
|
---|
178 | def Lock():
|
---|
179 | '''
|
---|
180 | Returns a non-recursive lock object
|
---|
181 | '''
|
---|
182 | from multiprocessing.synchronize import Lock
|
---|
183 | return Lock()
|
---|
184 |
|
---|
185 | def RLock():
|
---|
186 | '''
|
---|
187 | Returns a recursive lock object
|
---|
188 | '''
|
---|
189 | from multiprocessing.synchronize import RLock
|
---|
190 | return RLock()
|
---|
191 |
|
---|
192 | def Condition(lock=None):
|
---|
193 | '''
|
---|
194 | Returns a condition object
|
---|
195 | '''
|
---|
196 | from multiprocessing.synchronize import Condition
|
---|
197 | return Condition(lock)
|
---|
198 |
|
---|
199 | def Semaphore(value=1):
|
---|
200 | '''
|
---|
201 | Returns a semaphore object
|
---|
202 | '''
|
---|
203 | from multiprocessing.synchronize import Semaphore
|
---|
204 | return Semaphore(value)
|
---|
205 |
|
---|
206 | def BoundedSemaphore(value=1):
|
---|
207 | '''
|
---|
208 | Returns a bounded semaphore object
|
---|
209 | '''
|
---|
210 | from multiprocessing.synchronize import BoundedSemaphore
|
---|
211 | return BoundedSemaphore(value)
|
---|
212 |
|
---|
213 | def Event():
|
---|
214 | '''
|
---|
215 | Returns an event object
|
---|
216 | '''
|
---|
217 | from multiprocessing.synchronize import Event
|
---|
218 | return Event()
|
---|
219 |
|
---|
220 | def Queue(maxsize=0):
|
---|
221 | '''
|
---|
222 | Returns a queue object
|
---|
223 | '''
|
---|
224 | from multiprocessing.queues import Queue
|
---|
225 | return Queue(maxsize)
|
---|
226 |
|
---|
227 | def JoinableQueue(maxsize=0):
|
---|
228 | '''
|
---|
229 | Returns a queue object
|
---|
230 | '''
|
---|
231 | from multiprocessing.queues import JoinableQueue
|
---|
232 | return JoinableQueue(maxsize)
|
---|
233 |
|
---|
234 | def Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None):
|
---|
235 | '''
|
---|
236 | Returns a process pool object
|
---|
237 | '''
|
---|
238 | from multiprocessing.pool import Pool
|
---|
239 | return Pool(processes, initializer, initargs, maxtasksperchild)
|
---|
240 |
|
---|
241 | def RawValue(typecode_or_type, *args):
|
---|
242 | '''
|
---|
243 | Returns a shared object
|
---|
244 | '''
|
---|
245 | from multiprocessing.sharedctypes import RawValue
|
---|
246 | return RawValue(typecode_or_type, *args)
|
---|
247 |
|
---|
248 | def RawArray(typecode_or_type, size_or_initializer):
|
---|
249 | '''
|
---|
250 | Returns a shared array
|
---|
251 | '''
|
---|
252 | from multiprocessing.sharedctypes import RawArray
|
---|
253 | return RawArray(typecode_or_type, size_or_initializer)
|
---|
254 |
|
---|
255 | def Value(typecode_or_type, *args, **kwds):
|
---|
256 | '''
|
---|
257 | Returns a synchronized shared object
|
---|
258 | '''
|
---|
259 | from multiprocessing.sharedctypes import Value
|
---|
260 | return Value(typecode_or_type, *args, **kwds)
|
---|
261 |
|
---|
262 | def Array(typecode_or_type, size_or_initializer, **kwds):
|
---|
263 | '''
|
---|
264 | Returns a synchronized shared array
|
---|
265 | '''
|
---|
266 | from multiprocessing.sharedctypes import Array
|
---|
267 | return Array(typecode_or_type, size_or_initializer, **kwds)
|
---|
268 |
|
---|
269 | #
|
---|
270 | #
|
---|
271 | #
|
---|
272 |
|
---|
273 | if sys.platform == 'win32':
|
---|
274 |
|
---|
275 | def set_executable(executable):
|
---|
276 | '''
|
---|
277 | Sets the path to a python.exe or pythonw.exe binary used to run
|
---|
278 | child processes on Windows instead of sys.executable.
|
---|
279 | Useful for people embedding Python.
|
---|
280 | '''
|
---|
281 | from multiprocessing.forking import set_executable
|
---|
282 | set_executable(executable)
|
---|
283 |
|
---|
284 | __all__ += ['set_executable']
|
---|