Changeset 388 for python/vendor/current/Lib/runpy.py
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Lib/runpy.py
r2 r388 12 12 import sys 13 13 import imp 14 from pkgutil import read_code 14 15 try: 15 16 from imp import get_loader … … 18 19 19 20 __all__ = [ 20 "run_module", 21 "run_module", "run_path", 21 22 ] 22 23 24 class _TempModule(object): 25 """Temporarily replace a module in sys.modules with an empty namespace""" 26 def __init__(self, mod_name): 27 self.mod_name = mod_name 28 self.module = imp.new_module(mod_name) 29 self._saved_module = [] 30 31 def __enter__(self): 32 mod_name = self.mod_name 33 try: 34 self._saved_module.append(sys.modules[mod_name]) 35 except KeyError: 36 pass 37 sys.modules[mod_name] = self.module 38 return self 39 40 def __exit__(self, *args): 41 if self._saved_module: 42 sys.modules[self.mod_name] = self._saved_module[0] 43 else: 44 del sys.modules[self.mod_name] 45 self._saved_module = [] 46 47 class _ModifiedArgv0(object): 48 def __init__(self, value): 49 self.value = value 50 self._saved_value = self._sentinel = object() 51 52 def __enter__(self): 53 if self._saved_value is not self._sentinel: 54 raise RuntimeError("Already preserving saved value") 55 self._saved_value = sys.argv[0] 56 sys.argv[0] = self.value 57 58 def __exit__(self, *args): 59 self.value = self._sentinel 60 sys.argv[0] = self._saved_value 23 61 24 62 def _run_code(code, run_globals, init_globals=None, 25 63 mod_name=None, mod_fname=None, 26 64 mod_loader=None, pkg_name=None): 27 """Helper for _run_module_code"""65 """Helper to run code in nominated namespace""" 28 66 if init_globals is not None: 29 67 run_globals.update(init_globals) … … 38 76 mod_name=None, mod_fname=None, 39 77 mod_loader=None, pkg_name=None): 40 """Helper for run_module""" 41 # Set up the top level namespace dictionary 42 temp_module = imp.new_module(mod_name) 43 mod_globals = temp_module.__dict__ 44 # Modify sys.argv[0] and sys.module[mod_name] 45 saved_argv0 = sys.argv[0] 46 restore_module = mod_name in sys.modules 47 if restore_module: 48 saved_module = sys.modules[mod_name] 49 sys.argv[0] = mod_fname 50 sys.modules[mod_name] = temp_module 51 try: 78 """Helper to run code in new namespace with sys modified""" 79 with _TempModule(mod_name) as temp_module, _ModifiedArgv0(mod_fname): 80 mod_globals = temp_module.module.__dict__ 52 81 _run_code(code, mod_globals, init_globals, 53 mod_name, mod_fname, 54 mod_loader, pkg_name) 55 finally: 56 sys.argv[0] = saved_argv0 57 if restore_module: 58 sys.modules[mod_name] = saved_module 59 else: 60 del sys.modules[mod_name] 82 mod_name, mod_fname, mod_loader, pkg_name) 61 83 # Copy the globals of the temporary module, as they 62 84 # may be cleared when the temporary module goes away … … 81 103 raise ImportError("No module named %s" % mod_name) 82 104 if loader.is_package(mod_name): 83 raise ImportError(("%s is a package and cannot " + 84 "be directly executed") % mod_name) 105 if mod_name == "__main__" or mod_name.endswith(".__main__"): 106 raise ImportError("Cannot use package as __main__ module") 107 try: 108 pkg_main_name = mod_name + ".__main__" 109 return _get_module_details(pkg_main_name) 110 except ImportError, e: 111 raise ImportError(("%s; %r is a package and cannot " + 112 "be directly executed") %(e, mod_name)) 85 113 code = loader.get_code(mod_name) 86 114 if code is None: 87 115 raise ImportError("No code object available for %s" % mod_name) 88 116 filename = _get_filename(loader, mod_name) 89 return loader, code, filename 90 91 92 # XXX ncoghlan: Should this be documented and made public? 93 # (Current thoughts: don't repeat the mistake that lead to its 94 # creation when run_module() no longer met the needs of 95 # mainmodule.c, but couldn't be changed because it was public) 96 def _run_module_as_main(mod_name, set_argv0=True): 117 return mod_name, loader, code, filename 118 119 120 def _get_main_module_details(): 121 # Helper that gives a nicer error message when attempting to 122 # execute a zipfile or directory by invoking __main__.py 123 main_name = "__main__" 124 try: 125 return _get_module_details(main_name) 126 except ImportError as exc: 127 if main_name in str(exc): 128 raise ImportError("can't find %r module in %r" % 129 (main_name, sys.path[0])) 130 raise 131 132 # This function is the actual implementation of the -m switch and direct 133 # execution of zipfiles and directories and is deliberately kept private. 134 # This avoids a repeat of the situation where run_module() no longer met the 135 # needs of mainmodule.c, but couldn't be changed because it was public 136 def _run_module_as_main(mod_name, alter_argv=True): 97 137 """Runs the designated module in the __main__ namespace 98 138 99 These __*__ magic variables will be overwritten: 139 Note that the executed module will have full access to the 140 __main__ namespace. If this is not desirable, the run_module() 141 function should be used to run the module code in a fresh namespace. 142 143 At the very least, these variables in __main__ will be overwritten: 144 __name__ 100 145 __file__ 101 146 __loader__ 147 __package__ 102 148 """ 103 149 try: 104 loader, code, fname = _get_module_details(mod_name) 150 if alter_argv or mod_name != "__main__": # i.e. -m switch 151 mod_name, loader, code, fname = _get_module_details(mod_name) 152 else: # i.e. directory or zipfile execution 153 mod_name, loader, code, fname = _get_main_module_details() 105 154 except ImportError as exc: 106 # Try to provide a good error message 107 # for directories, zip files and the -m switch 108 if set_argv0: 109 # For -m switch, just disply the exception 110 info = str(exc) 111 else: 112 # For directories/zipfiles, let the user 113 # know what the code was looking for 114 info = "can't find '__main__.py' in %r" % sys.argv[0] 115 msg = "%s: %s" % (sys.executable, info) 155 msg = "%s: %s" % (sys.executable, str(exc)) 116 156 sys.exit(msg) 117 157 pkg_name = mod_name.rpartition('.')[0] 118 158 main_globals = sys.modules["__main__"].__dict__ 119 if set_argv0:159 if alter_argv: 120 160 sys.argv[0] = fname 121 161 return _run_code(code, main_globals, None, … … 128 168 Returns the resulting top level namespace dictionary 129 169 """ 130 loader, code, fname = _get_module_details(mod_name)170 mod_name, loader, code, fname = _get_module_details(mod_name) 131 171 if run_name is None: 132 172 run_name = mod_name … … 141 181 142 182 183 # XXX (ncoghlan): Perhaps expose the C API function 184 # as imp.get_importer instead of reimplementing it in Python? 185 def _get_importer(path_name): 186 """Python version of PyImport_GetImporter C API function""" 187 cache = sys.path_importer_cache 188 try: 189 importer = cache[path_name] 190 except KeyError: 191 # Not yet cached. Flag as using the 192 # standard machinery until we finish 193 # checking the hooks 194 cache[path_name] = None 195 for hook in sys.path_hooks: 196 try: 197 importer = hook(path_name) 198 break 199 except ImportError: 200 pass 201 else: 202 # The following check looks a bit odd. The trick is that 203 # NullImporter raises ImportError if the supplied path is a 204 # *valid* directory entry (and hence able to be handled 205 # by the standard import machinery) 206 try: 207 importer = imp.NullImporter(path_name) 208 except ImportError: 209 return None 210 cache[path_name] = importer 211 return importer 212 213 def _get_code_from_file(fname): 214 # Check for a compiled file first 215 with open(fname, "rb") as f: 216 code = read_code(f) 217 if code is None: 218 # That didn't work, so try it as normal source code 219 with open(fname, "rU") as f: 220 code = compile(f.read(), fname, 'exec') 221 return code 222 223 def run_path(path_name, init_globals=None, run_name=None): 224 """Execute code located at the specified filesystem location 225 226 Returns the resulting top level namespace dictionary 227 228 The file path may refer directly to a Python script (i.e. 229 one that could be directly executed with execfile) or else 230 it may refer to a zipfile or directory containing a top 231 level __main__.py script. 232 """ 233 if run_name is None: 234 run_name = "<run_path>" 235 importer = _get_importer(path_name) 236 if isinstance(importer, imp.NullImporter): 237 # Not a valid sys.path entry, so run the code directly 238 # execfile() doesn't help as we want to allow compiled files 239 code = _get_code_from_file(path_name) 240 return _run_module_code(code, init_globals, run_name, path_name) 241 else: 242 # Importer is defined for path, so add it to 243 # the start of sys.path 244 sys.path.insert(0, path_name) 245 try: 246 # Here's where things are a little different from the run_module 247 # case. There, we only had to replace the module in sys while the 248 # code was running and doing so was somewhat optional. Here, we 249 # have no choice and we have to remove it even while we read the 250 # code. If we don't do this, a __loader__ attribute in the 251 # existing __main__ module may prevent location of the new module. 252 main_name = "__main__" 253 saved_main = sys.modules[main_name] 254 del sys.modules[main_name] 255 try: 256 mod_name, loader, code, fname = _get_main_module_details() 257 finally: 258 sys.modules[main_name] = saved_main 259 pkg_name = "" 260 with _TempModule(run_name) as temp_module, \ 261 _ModifiedArgv0(path_name): 262 mod_globals = temp_module.module.__dict__ 263 return _run_code(code, mod_globals, init_globals, 264 run_name, fname, loader, pkg_name).copy() 265 finally: 266 try: 267 sys.path.remove(path_name) 268 except ValueError: 269 pass 270 271 143 272 if __name__ == "__main__": 144 273 # Run the module specified as the next command line argument
Note:
See TracChangeset
for help on using the changeset viewer.