📄 importer.py
字号:
def modules_graph(self, verbose=0): self._lock1.acquire() try: output = StringIO.StringIO() modules = self._cache print >> output, 'digraph GLOBAL {' print >> output, 'node [shape=box];' for cache in modules.values(): name = cache.label filename = cache.file if verbose: ctime = time.asctime(time.localtime(cache.ctime)) mtime = time.asctime(time.localtime(cache.mtime)) atime = time.asctime(time.localtime(cache.atime)) generation = cache.generation direct = cache.direct indirect = cache.indirect path = cache.path message = '%s [label="%s\\nmtime = %s\\nctime = %s\\n' message += 'atime = %s\\ngeneration = %d, direct = %d,' message += 'indirect = %d\\npath = %s"];' print >> output, message % (name, filename, mtime, ctime, atime, generation, direct, indirect, path) else: message = '%s [label="%s"];' print >> output, message % (name, filename) children = cache.children for child_name in children: print >> output, '%s -> %s' % (name, child_name) print >> output, '}' return output.getvalue() finally: self._lock1.release() def _check_directory(self, file): directory = os.path.dirname(file) if not directory in self._directories: self._directories[directory] = None if directory in sys.path: msg = 'Module directory listed in "sys.path". ' msg = msg + 'This may cause problems. Please check code. ' msg = msg + 'File being imported is "%s".' % file self._log_warning(msg) def import_module(self, file, autoreload=None, log=None, path=None): # Ensure that file name is normalised so all # lookups against the cache equate where they # are the same file. This isn't necessarily # going to work where symlinks are involved, but # not much else that can be done in that case. file = os.path.normpath(file) # Determine the default values for the module # autoreloading and logging arguments direct # from the Apache configuration rather than # having fixed defaults. if autoreload is None or log is None: config = get_current_config() if autoreload is None: autoreload = int(config.get("PythonAutoReload", 1)) if log is None: log = int(config.get("PythonDebug", 0)) # Warn of any instances where a code file is # imported from a directory which also appears # in 'sys.path'. if log: self._check_directory(file) # Retrieve the parent context. That is, the # details stashed into the parent module by the # module importing system itself. (parent_info, parent_path) = _parent_context() # Check for an attempt by the module to import # itself. if parent_info: assert(file != parent_info.file), "Import cycle in %s." % file # Retrieve the per request modules cache entry. modules = _get_request_modules_cache() # Calculate a unique label corresponding to the # name of the file which is the module. This # will be used as the '__name__' attribute of a # module and as key in various tables. label = self._module_label(file) # See if the requested module has already been # imported previously within the context of this # request or at least visited by way of prior # dependency checks where it was deemed that it # didn't need to be reloaded. If it has we can # skip any additional dependency checks and use # the module already identified. This ensures # the same actual module instance is used. This # check is also required so that we don't get # into cyclical import loops. Still need to at # least record the fact that the module is a # child of the parent. if modules is not None: if modules.has_key(label): if parent_info: parent_info.children[label] = time.time() return modules[label] # Now move on to trying to find the actual # module. try: cache = None # First determine if the module has been loaded # previously. If not already loaded or if a # dependency of the module has been changed on disk # or reloaded since parent was loaded, must load the # module. (cache, load) = self._reload_required(modules, label, file, autoreload) # Make sure that the cache entry is locked by the # thread so that other threads in a multithreaded # system don't try and load the same module at the # same time. cache.lock.acquire() # If this per request modules cache has just # been created for the first time, record some # details in it about current cache state and # run time of the request. if modules.ctime == 0: modules.generation = self._generation modules.ctime = time.time() # Import module or obtain it from cache as is # appropriate. if load: # Setup a new empty module to load the code for # the module into. Increment the instance count # and set the reload flag to force a reload if # the import fails. cache.instance = cache.instance + 1 cache.reload = 1 module = imp.new_module(label) # If the module was previously loaded we need to # manage the transition to the new instance of # the module that is being loaded to replace it. # This entails calling the special clone method, # if provided within the existing module. Using # this method the existing module can then # selectively indicate what should be transfered # over to the next instance of the module, # including thread locks. If this process fails # the special purge method is called, if # provided, to indicate that the existing module # is being forcibly purged out of the system. In # that case any existing state will not be # transferred. if cache.module != None: if hasattr(cache.module, "__mp_clone__"): try: # Migrate any existing state data from # existing module instance to new module # instance. if log: msg = "Cloning module '%s'" % file self._log_notice(msg) cache.module.__mp_clone__(module) except: # Forcibly purging module from system. self._log_exception() if log: msg = "Purging module '%s'" % file self._log_notice(msg) if hasattr(cache.module, "__mp_purge__"): try: cache.module.__mp_purge__() except: self._log_exception() cache.module = None # Setup a fresh new module yet again. module = imp.new_module(label) if log: if cache.module == None: msg = "Importing module '%s'" % file self._log_notice(msg) else: msg = "Reimporting module '%s'" % file self._log_notice(msg) else: if log: msg = "Importing module '%s'" % file self._log_notice(msg) # Must add to the module the path to the modules # file. This ensures that module looks like a # normal module and this path will also be used # in certain contexts when the import statement # is used within the module. module.__file__ = file # Setup a new instance object to store in the # module. This will refer back to the actual # cache entry and is used to record information # which is specific to this incarnation of the # module when reloading is occuring. instance = _InstanceInfo(label, file, cache) module.__mp_info__ = instance # Cache any additional module search path which # should be used for this instance of the module # or package. The path shouldn't be able to be # changed during the lifetime of the module to # ensure that module imports are always done # against the same path. if path is None: path = [] module.__mp_path__ = list(path) # Place a reference to the module within the # request specific cache of imported modules. # This makes module lookup more efficient when # the same module is imported more than once # within the context of a request. In the case # of a cyclical import, avoids a never ending # recursive loop. if modules is not None: modules[label] = module # If this is a child import of some parent # module, add this module as a child of the # parent. atime = time.time() if parent_info: parent_info.children[label] = atime # Perform actual import of the module. try: execfile(file, module.__dict__) except: # Importation of the module has failed for # some reason. If this is the very first # import of the module, need to discard the # cache entry entirely else a subsequent # attempt to load the module will wrongly # think it was successfully loaded already. if cache.module is None: del self._cache[label] raise # Update the cache and clear the reload flag. cache.module = module cache.reload = 0 # Need to also update the list of child modules # stored in the cache entry with the actual # children found during the import. A copy is # made, meaning that any future imports # performed within the context of the request # handler don't result in the module later being # reloaded if they change. cache.children = dict(module.__mp_info__.children) # Create link to embedded path at end of import. cache.path = module.__mp_path__ # Increment the generation count of the global # state of all modules. This is used in the # dependency management scheme for reloading to # determine if a module dependency has been # reloaded since it was loaded. self._lock2.acquire() self._generation = self._generation + 1 cache.generation = self._generation self._lock2.release() # Update access time and reset access counts. cache.ctime = atime cache.atime = atime cache.direct = 1 cache.indirect = 0 else: # Update the cache. module = cache.module # Place a reference to the module within the # request specific cache of imported modules. # This makes module lookup more efficient when # the same module is imported more than once # within the context of a request. In the case # of a cyclical import, avoids a never ending # recursive loop. if modules is not None: modules[label] = module # If this is a child import of some parent # module, add this module as a child of the # parent. atime = time.time() if parent_info: parent_info.children[label] = atime # Didn't need to reload the module so simply # increment access counts and last access time. cache.atime = atime cache.direct = cache.direct + 1 return module finally: # Lock on cache object can now be released. if cache is not None: cache.lock.release() def _reload_required(self, modules, label, file, autoreload): # Make sure cache lock is always released. try: self._lock1.acquire() # Check if this is a new module.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -