10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Module for starting a process object using os.fork() or CreateProcess() 30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# multiprocessing/forking.py 50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Copyright (c) 2006-2008, R Oudkerk 70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# All rights reserved. 80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Redistribution and use in source and binary forms, with or without 100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# modification, are permitted provided that the following conditions 110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# are met: 120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 1. Redistributions of source code must retain the above copyright 140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# notice, this list of conditions and the following disclaimer. 150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 2. Redistributions in binary form must reproduce the above copyright 160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# notice, this list of conditions and the following disclaimer in the 170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# documentation and/or other materials provided with the distribution. 180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 3. Neither the name of author nor the names of any contributors may be 190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# used to endorse or promote products derived from this software 200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# without specific prior written permission. 210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# SUCH DAMAGE. 330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 350a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os 360a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys 370a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport signal 380a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport errno 390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 400a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom multiprocessing import util, process 410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__all__ = ['Popen', 'assert_spawning', 'exit', 'duplicate', 'close', 'ForkingPickler'] 430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Check that the current thread is spawning a child process 460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 480a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef assert_spawning(self): 490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not Popen.thread_is_spawning(): 500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise RuntimeError( 510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao '%s objects should only be shared between processes' 520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ' through inheritance' % type(self).__name__ 530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Try making some callable types picklable 570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 590a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom pickle import Pickler 600a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass ForkingPickler(Pickler): 610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dispatch = Pickler.dispatch.copy() 620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao @classmethod 640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def register(cls, type, reduce): 650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def dispatcher(self, obj): 660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rv = reduce(obj) 670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.save_reduce(obj=obj, *rv) 680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cls.dispatch[type] = dispatcher 690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 700a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _reduce_method(m): 710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if m.im_self is None: 720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return getattr, (m.im_class, m.im_func.func_name) 730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return getattr, (m.im_self, m.im_func.func_name) 750a8c90248264a8b26970b4473770bcc3df8515fJosh GaoForkingPickler.register(type(ForkingPickler.save), _reduce_method) 760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 770a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _reduce_method_descriptor(m): 780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return getattr, (m.__objclass__, m.__name__) 790a8c90248264a8b26970b4473770bcc3df8515fJosh GaoForkingPickler.register(type(list.append), _reduce_method_descriptor) 800a8c90248264a8b26970b4473770bcc3df8515fJosh GaoForkingPickler.register(type(int.__add__), _reduce_method_descriptor) 810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#def _reduce_builtin_function_or_method(m): 830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# return getattr, (m.__self__, m.__name__) 840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#ForkingPickler.register(type(list().append), _reduce_builtin_function_or_method) 850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#ForkingPickler.register(type(int().__add__), _reduce_builtin_function_or_method) 860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 870a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry: 880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from functools import partial 890a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept ImportError: 900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pass 910a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoelse: 920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _reduce_partial(p): 930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return _rebuild_partial, (p.func, p.args, p.keywords or {}) 940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _rebuild_partial(func, args, keywords): 950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return partial(func, *args, **keywords) 960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ForkingPickler.register(partial, _reduce_partial) 970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Unix 1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif sys.platform != 'win32': 1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import time 1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao exit = os._exit 1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao duplicate = os.dup 1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao close = os.close 1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # We define a Popen class similar to the one from subprocess, but 1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # whose constructor takes a process object as its argument. 1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao class Popen(object): 1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __init__(self, process_obj): 1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.stdout.flush() 1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.stderr.flush() 1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.returncode = None 1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.pid = os.fork() 1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.pid == 0: 1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'random' in sys.modules: 1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import random 1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao random.seed() 1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao code = process_obj._bootstrap() 1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.stdout.flush() 1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.stderr.flush() 1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os._exit(code) 1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def poll(self, flag=os.WNOHANG): 1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.returncode is None: 1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao while True: 1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pid, sts = os.waitpid(self.pid, flag) 1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except os.error as e: 1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if e.errno == errno.EINTR: 1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao continue 1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Child process not yet created. See #1731717 1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # e.errno == errno.ECHILD == 10 1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return None 1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao break 1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if pid == self.pid: 1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if os.WIFSIGNALED(sts): 1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.returncode = -os.WTERMSIG(sts) 1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao assert os.WIFEXITED(sts) 1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.returncode = os.WEXITSTATUS(sts) 1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.returncode 1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def wait(self, timeout=None): 1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if timeout is None: 1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.poll(0) 1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao deadline = time.time() + timeout 1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao delay = 0.0005 1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao while 1: 1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao res = self.poll() 1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if res is not None: 1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao break 1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao remaining = deadline - time.time() 1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if remaining <= 0: 1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao break 1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao delay = min(delay * 2, remaining, 0.05) 1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao time.sleep(delay) 1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return res 1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def terminate(self): 1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.returncode is None: 1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.kill(self.pid, signal.SIGTERM) 1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except OSError, e: 1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.wait(timeout=0.1) is None: 1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise 1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao @staticmethod 1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def thread_is_spawning(): 1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return False 1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Windows 1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoelse: 1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import thread 1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import msvcrt 1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import _subprocess 1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import time 1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from _multiprocessing import win32, Connection, PipeConnection 1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from .util import Finalize 1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao #try: 1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # from cPickle import dump, load, HIGHEST_PROTOCOL 1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao #except ImportError: 1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from pickle import load, HIGHEST_PROTOCOL 1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def dump(obj, file, protocol=None): 1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ForkingPickler(file, protocol).dump(obj) 2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao TERMINATE = 0x10000 2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False)) 2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao WINSERVICE = sys.executable.lower().endswith("pythonservice.exe") 2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao exit = win32.ExitProcess 2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao close = win32.CloseHandle 2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # _python_exe is the assumed path to the python executable. 2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # People embedding Python want to modify it. 2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if WINSERVICE: 2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _python_exe = os.path.join(sys.exec_prefix, 'python.exe') 2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _python_exe = sys.executable 2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def set_executable(exe): 2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao global _python_exe 2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _python_exe = exe 2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def duplicate(handle, target_process=None, inheritable=False): 2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if target_process is None: 2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao target_process = _subprocess.GetCurrentProcess() 2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return _subprocess.DuplicateHandle( 2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _subprocess.GetCurrentProcess(), handle, target_process, 2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 0, inheritable, _subprocess.DUPLICATE_SAME_ACCESS 2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ).Detach() 2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # We define a Popen class similar to the one from subprocess, but 2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # whose constructor takes a process object as its argument. 2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao class Popen(object): 2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Start a subprocess to run the code of a process object 2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _tls = thread._local() 2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __init__(self, process_obj): 2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # create pipe for communication with child 2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rfd, wfd = os.pipe() 2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # get handle for read end of the pipe and make it inheritable 2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rhandle = duplicate(msvcrt.get_osfhandle(rfd), inheritable=True) 2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.close(rfd) 2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # start process 2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cmd = get_command_line() + [rhandle] 2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao cmd = ' '.join('"%s"' % x for x in cmd) 2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao hp, ht, pid, tid = _subprocess.CreateProcess( 2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _python_exe, cmd, None, None, 1, 0, None, None, None 2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ht.Close() 2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao close(rhandle) 2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # set attributes of self 2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.pid = pid 2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.returncode = None 2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._handle = hp 2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # send information to child 2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao prep_data = get_preparation_data(process_obj._name) 2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao to_child = os.fdopen(wfd, 'wb') 2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Popen._tls.process_handle = int(hp) 2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dump(prep_data, to_child, HIGHEST_PROTOCOL) 2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dump(process_obj, to_child, HIGHEST_PROTOCOL) 2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao finally: 2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao del Popen._tls.process_handle 2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao to_child.close() 2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao @staticmethod 2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def thread_is_spawning(): 2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return getattr(Popen._tls, 'process_handle', None) is not None 2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao @staticmethod 2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def duplicate_for_child(handle): 2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return duplicate(handle, Popen._tls.process_handle) 2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def wait(self, timeout=None): 2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.returncode is None: 2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if timeout is None: 2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao msecs = _subprocess.INFINITE 2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao msecs = max(0, int(timeout * 1000 + 0.5)) 2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao res = _subprocess.WaitForSingleObject(int(self._handle), msecs) 2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if res == _subprocess.WAIT_OBJECT_0: 2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao code = _subprocess.GetExitCodeProcess(self._handle) 3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if code == TERMINATE: 3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao code = -signal.SIGTERM 3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.returncode = code 3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.returncode 3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def poll(self): 3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.wait(timeout=0) 3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def terminate(self): 3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.returncode is None: 3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _subprocess.TerminateProcess(int(self._handle), TERMINATE) 3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except WindowsError: 3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.wait(timeout=0.1) is None: 3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise 3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def is_forking(argv): 3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Return whether commandline indicates we are forking 3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if len(argv) >= 2 and argv[1] == '--multiprocessing-fork': 3260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao assert len(argv) == 3 3270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return True 3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return False 3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def freeze_support(): 3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Run code for process object if this in not the main process 3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if is_forking(sys.argv): 3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main() 3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.exit() 3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get_command_line(): 3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Returns prefix of command line used for spawning a child process 3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if getattr(process.current_process(), '_inheriting', False): 3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise RuntimeError(''' 3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Attempt to start a new process before the current process 3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao has finished its bootstrapping phase. 3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao This probably means that you are on Windows and you have 3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao forgotten to use the proper idiom in the main module: 3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if __name__ == '__main__': 3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao freeze_support() 3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ... 3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao The "freeze_support()" line can be omitted if the program 3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao is not going to be frozen to produce a Windows executable.''') 3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if getattr(sys, 'frozen', False): 3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return [sys.executable, '--multiprocessing-fork'] 3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao prog = 'from multiprocessing.forking import main; main()' 3640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao opts = util._args_from_interpreter_flags() 3650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return [_python_exe] + opts + ['-c', prog, '--multiprocessing-fork'] 3660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def main(): 3690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Run code specifed by data received over pipe 3710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao assert is_forking(sys.argv) 3730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao handle = int(sys.argv[-1]) 3750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fd = msvcrt.open_osfhandle(handle, os.O_RDONLY) 3760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from_parent = os.fdopen(fd, 'rb') 3770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao process.current_process()._inheriting = True 3790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao preparation_data = load(from_parent) 3800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao prepare(preparation_data) 3810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self = load(from_parent) 3820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao process.current_process()._inheriting = False 3830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from_parent.close() 3850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao exitcode = self._bootstrap() 3870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao exit(exitcode) 3880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get_preparation_data(name): 3910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Return info about parent needed by child to unpickle process object 3930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 3940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from .util import _logger, _log_to_stderr 3950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 3960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao d = dict( 3970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao name=name, 3980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys_path=sys.path, 3990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys_argv=sys.argv, 4000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao log_to_stderr=_log_to_stderr, 4010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao orig_dir=process.ORIGINAL_DIR, 4020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao authkey=process.current_process().authkey, 4030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 4040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if _logger is not None: 4060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao d['log_level'] = _logger.getEffectiveLevel() 4070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not WINEXE and not WINSERVICE: 4090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_path = getattr(sys.modules['__main__'], '__file__', None) 4100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not main_path and sys.argv[0] not in ('', '-c'): 4110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_path = sys.argv[0] 4120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if main_path is not None: 4130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not os.path.isabs(main_path) and \ 4140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao process.ORIGINAL_DIR is not None: 4150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_path = os.path.join(process.ORIGINAL_DIR, main_path) 4160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao d['main_path'] = os.path.normpath(main_path) 4170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return d 4190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 4210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Make (Pipe)Connection picklable 4220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # 4230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def reduce_connection(conn): 4250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not Popen.thread_is_spawning(): 4260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise RuntimeError( 4270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 'By default %s objects can only be shared between processes\n' 4280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 'using inheritance' % type(conn).__name__ 4290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 4300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return type(conn), (Popen.duplicate_for_child(conn.fileno()), 4310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao conn.readable, conn.writable) 4320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ForkingPickler.register(Connection, reduce_connection) 4340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ForkingPickler.register(PipeConnection, reduce_connection) 4350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 4370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Prepare current process 4380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 4390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4400a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoold_main_modules = [] 4410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4420a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef prepare(data): 4430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 4440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Try to get current process ready to unpickle process object 4450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ''' 4460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao old_main_modules.append(sys.modules['__main__']) 4470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'name' in data: 4490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao process.current_process().name = data['name'] 4500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'authkey' in data: 4520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao process.current_process()._authkey = data['authkey'] 4530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'log_to_stderr' in data and data['log_to_stderr']: 4550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao util.log_to_stderr() 4560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'log_level' in data: 4580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao util.get_logger().setLevel(data['log_level']) 4590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'sys_path' in data: 4610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.path = data['sys_path'] 4620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'sys_argv' in data: 4640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.argv = data['sys_argv'] 4650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'dir' in data: 4670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.chdir(data['dir']) 4680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'orig_dir' in data: 4700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao process.ORIGINAL_DIR = data['orig_dir'] 4710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if 'main_path' in data: 4730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_path = data['main_path'] 4740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_name = os.path.splitext(os.path.basename(main_path))[0] 4750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if main_name == '__init__': 4760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_name = os.path.basename(os.path.dirname(main_path)) 4770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if main_name != 'ipython': 4790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import imp 4800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if main_path is None: 4820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dirs = None 4830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif os.path.basename(main_path).startswith('__init__.py'): 4840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dirs = [os.path.dirname(os.path.dirname(main_path))] 4850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 4860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dirs = [os.path.dirname(main_path)] 4870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 4880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao assert main_name not in sys.modules, main_name 4890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file, path_name, etc = imp.find_module(main_name, dirs) 4900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 4910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # We would like to do "imp.load_module('__main__', ...)" 4920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # here. However, that would cause 'if __name__ == 4930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # "__main__"' clauses to be executed. 4940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_module = imp.load_module( 4950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao '__parents_main__', file, path_name, etc 4960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 4970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao finally: 4980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if file: 4990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao file.close() 5000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 5010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.modules['__main__'] = main_module 5020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao main_module.__name__ = '__main__' 5030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 5040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Try to make the potentially picklable objects in 5050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # sys.modules['__main__'] realize they are in the main 5060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # module -- somewhat ugly. 5070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for obj in main_module.__dict__.values(): 5080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 5090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if obj.__module__ == '__parents_main__': 5100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao obj.__module__ = '__main__' 5110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except Exception: 5120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pass 513