From 9ec54544d983489183076006c08124dc6ea3d8b5 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 12 Aug 2010 13:59:26 -0400 Subject: [PATCH] Add hooke.compat.forking to fix Python's ImportError issue8534. multiprocessing can have problems importing modules from child processes. See http://bugs.python.org/issue8534 http://code.google.com/p/hooke/issues/detail?id=40#c17 Importing hooke.compat.forking fixes this bug dynamically. --- hooke/compat/forking.py | 109 ++++++++++++++++++++++++++++++++++++++++ hooke/hooke.py | 1 + 2 files changed, 110 insertions(+) create mode 100644 hooke/compat/forking.py diff --git a/hooke/compat/forking.py b/hooke/compat/forking.py new file mode 100644 index 0000000..9acf816 --- /dev/null +++ b/hooke/compat/forking.py @@ -0,0 +1,109 @@ +# Copyright (C) 2010 W. Trevor King +# +# This file is part of Hooke. +# +# Hooke is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Hooke is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Hooke. If not, see +# . + +"""Dynamically patch :func:`multiprocessing.forking.prepare`. + +`prepare` can have trouble `loading modules from .eggs`_ or +`finding hooke on Windows`_. Importing this module applies the +suggested patch dynamically. + +.. _loading modules from .eggs: http://bugs.python.org/issue8534 +.. _finding hooke on Windows: + http://code.google.com/p/hooke/issues/detail?id=40#c17 +""" + +import multiprocessing.forking + + +def prepare(data): + ''' + Try to get current process ready to unpickle process object + ''' + old_main_modules.append(sys.modules['__main__']) + + if 'name' in data: + process.current_process().name = data['name'] + + if 'authkey' in data: + process.current_process()._authkey = data['authkey'] + + if 'log_to_stderr' in data and data['log_to_stderr']: + util.log_to_stderr() + + if 'log_level' in data: + util.get_logger().setLevel(data['log_level']) + + if 'sys_path' in data: + sys.path = data['sys_path'] + + if 'sys_argv' in data: + sys.argv = data['sys_argv'] + + if 'dir' in data: + os.chdir(data['dir']) + + if 'orig_dir' in data: + process.ORIGINAL_DIR = data['orig_dir'] + + if 'main_path' in data: + main_path = data['main_path'] + main_name = os.path.splitext(os.path.basename(main_path))[0] + if main_name == '__init__': + main_name = os.path.basename(os.path.dirname(main_path)) + + if main_name != 'ipython': + import imp + + if main_path is None: + dirs = None + elif os.path.basename(main_path).startswith('__init__.py'): + dirs = [os.path.dirname(os.path.dirname(main_path))] + else: + dirs = [os.path.dirname(main_path)] + + assert main_name not in sys.modules, main_name + + try: + main_module = __import__(main_name) + except ImportError: + file, path_name, etc = imp.find_module(main_name, dirs) + + try: + # We would like to do "imp.load_module('__main__', ...)" + # here. However, that would cause 'if __name__ == + # "__main__"' clauses to be executed. + main_module = imp.load_module( + '__parents_main__', file, path_name, etc + ) + finally: + if file: + file.close() + + sys.modules['__main__'] = main_module + main_module.__name__ = '__main__' + + # Try to make the potentially picklable objects in + # sys.modules['__main__'] realize they are in the main + # module -- somewhat ugly. + for obj in main_module.__dict__.values(): + try: + if obj.__module__ == '__parents_main__': + obj.__module__ = '__main__' + except Exception: + pass +multiprocessing.forking.prepare = prepare diff --git a/hooke/hooke.py b/hooke/hooke.py index d9def05..c4b2200 100644 --- a/hooke/hooke.py +++ b/hooke/hooke.py @@ -71,6 +71,7 @@ from . import playlist from . import plugin as plugin_mod from . import driver as driver_mod from . import ui +from .compat import forking as forking # dynamically patch multiprocessing.forking class Hooke (object): -- 2.26.2