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
61import os
62import sys
63
64from multiprocessing.process import Process, current_process, active_children
65from multiprocessing.util import SUBDEBUG, SUBWARNING
66
67#
68# Exceptions
69#
70
71class ProcessError(Exception):
72    pass
73
74class BufferTooShort(ProcessError):
75    pass
76
77class TimeoutError(ProcessError):
78    pass
79
80class AuthenticationError(ProcessError):
81    pass
82
83# This is down here because _multiprocessing uses BufferTooShort
84import _multiprocessing
85
86#
87# Definitions not depending on native semaphores
88#
89
90def 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
102def 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
109def 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 = os.sysconf('SC_NPROCESSORS_ONLN')
130        except (ValueError, OSError, AttributeError):
131            num = 0
132
133    if num >= 1:
134        return num
135    else:
136        raise NotImplementedError('cannot determine number of cpus')
137
138def freeze_support():
139    '''
140    Check whether this is a fake forked process in a frozen executable.
141    If so then run code specified by commandline and exit.
142    '''
143    if sys.platform == 'win32' and getattr(sys, 'frozen', False):
144        from multiprocessing.forking import freeze_support
145        freeze_support()
146
147def get_logger():
148    '''
149    Return package logger -- if it does not already exist then it is created
150    '''
151    from multiprocessing.util import get_logger
152    return get_logger()
153
154def log_to_stderr(level=None):
155    '''
156    Turn on logging and add a handler which prints to stderr
157    '''
158    from multiprocessing.util import log_to_stderr
159    return log_to_stderr(level)
160
161def allow_connection_pickling():
162    '''
163    Install support for sending connections and sockets between processes
164    '''
165    from multiprocessing import reduction
166
167#
168# Definitions depending on native semaphores
169#
170
171def Lock():
172    '''
173    Returns a non-recursive lock object
174    '''
175    from multiprocessing.synchronize import Lock
176    return Lock()
177
178def RLock():
179    '''
180    Returns a recursive lock object
181    '''
182    from multiprocessing.synchronize import RLock
183    return RLock()
184
185def Condition(lock=None):
186    '''
187    Returns a condition object
188    '''
189    from multiprocessing.synchronize import Condition
190    return Condition(lock)
191
192def Semaphore(value=1):
193    '''
194    Returns a semaphore object
195    '''
196    from multiprocessing.synchronize import Semaphore
197    return Semaphore(value)
198
199def BoundedSemaphore(value=1):
200    '''
201    Returns a bounded semaphore object
202    '''
203    from multiprocessing.synchronize import BoundedSemaphore
204    return BoundedSemaphore(value)
205
206def Event():
207    '''
208    Returns an event object
209    '''
210    from multiprocessing.synchronize import Event
211    return Event()
212
213def Queue(maxsize=0):
214    '''
215    Returns a queue object
216    '''
217    from multiprocessing.queues import Queue
218    return Queue(maxsize)
219
220def JoinableQueue(maxsize=0):
221    '''
222    Returns a queue object
223    '''
224    from multiprocessing.queues import JoinableQueue
225    return JoinableQueue(maxsize)
226
227def Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None):
228    '''
229    Returns a process pool object
230    '''
231    from multiprocessing.pool import Pool
232    return Pool(processes, initializer, initargs, maxtasksperchild)
233
234def RawValue(typecode_or_type, *args):
235    '''
236    Returns a shared object
237    '''
238    from multiprocessing.sharedctypes import RawValue
239    return RawValue(typecode_or_type, *args)
240
241def RawArray(typecode_or_type, size_or_initializer):
242    '''
243    Returns a shared array
244    '''
245    from multiprocessing.sharedctypes import RawArray
246    return RawArray(typecode_or_type, size_or_initializer)
247
248def Value(typecode_or_type, *args, **kwds):
249    '''
250    Returns a synchronized shared object
251    '''
252    from multiprocessing.sharedctypes import Value
253    return Value(typecode_or_type, *args, **kwds)
254
255def Array(typecode_or_type, size_or_initializer, **kwds):
256    '''
257    Returns a synchronized shared array
258    '''
259    from multiprocessing.sharedctypes import Array
260    return Array(typecode_or_type, size_or_initializer, **kwds)
261
262#
263#
264#
265
266if sys.platform == 'win32':
267
268    def set_executable(executable):
269        '''
270        Sets the path to a python.exe or pythonw.exe binary used to run
271        child processes on Windows instead of sys.executable.
272        Useful for people embedding Python.
273        '''
274        from multiprocessing.forking import set_executable
275        set_executable(executable)
276
277    __all__ += ['set_executable']
278