Skip to content

Instantly share code, notes, and snippets.

@Yaiba
Last active August 29, 2015 14:23
Show Gist options
  • Save Yaiba/71ea3ea3cf096c37b7cb to your computer and use it in GitHub Desktop.
Save Yaiba/71ea3ea3cf096c37b7cb to your computer and use it in GitHub Desktop.

##tornado-debug 原理

使用方法: $ tor-deb python -m wcms_front.server

原理流程:

  1. 把/usr/lib/python2.7/site-packages/tornado_debug/bootstrap添加到环境变量PYTHONPATH

  2. 使用os.execl开启子进程,运行python程序

  3. python的site模块会执行bootstrap下的sitecustomize.py, 我们在sitecustomize.py中设置了import-hook

  4. 从sys.path中删除/usr/lib/python2.7/site-packages/tornado_debug/bootstrap

  5. 执行目标程序

##import hook 如果没有特殊设置,python会从sys.path列表中的路径下,查找module, 另外,python 还提供了两种hook方法, 可以在默认导入方法执行前使用。 ####sys.path_hooks 当导入模块时, sys.path 中的每一个路径会按顺序出入sys.path_hooks中的每个finder, 知道某个finder没有抛出ImportError,则该模块的导入会交给这个finder执行。finder 先执行 find_module, 如果找到了改模块,返回一个loader, loader执行 load_module. 当然也可以简化,将load_module 和 fnd_module的工作放到find_module, 而不返回loader。

import sys

class NoisyImportFinder(object):
    
    PATH_TRIGGER = 'NoisyImportFinder_PATH_TRIGGER'
    
    def __init__(self, path_entry):
        print 'Checking NoisyImportFinder support for %s' % path_entry
        if path_entry != self.PATH_TRIGGER:
            print 'NoisyImportFinder does not work for %s' % path_entry
            raise ImportError()
        return
    
    def find_module(self, fullname, path=None):
        print 'NoisyImportFinder looking for "%s"' % fullname
        return None

sys.path_hooks.append(NoisyImportFinder)

sys.path.insert(0, NoisyImportFinder.PATH_TRIGGER)

try:
    import target_module
except Exception, e:
    print 'Import failed:', e

####sys.meta_path

sys.meta_path列表内的hook 会在sys.path_hooks之前调用。 python会把代码中描述的模块的路径传入每一个sys.meta_path内的hook, 直到某个hook返回一个loader, 再使用这个loader加载模块.

class ImportHookFinder:

    def __init__(self):
        self._skip = {}

    def find_module(self, fullname, path=None):

        # If not something we are interested in we can return.

        if fullname not in _import_hooks:
            return None

        # Check whether this is being called on the second time
        # through and return.

        if fullname in self._skip:
            return None

        # We are now going to call back into import. We set a
        # flag to see we are handling the module so that check
        # above drops out on subsequent pass and we don't go
        # into an infinite loop.

        self._skip[fullname] = True

        try:
            __import__(fullname)
            return _ImportHookLoader()
        finally:
            del self._skip[fullname]


class _ImportHookLoader:

    def load_module(self, fullname):

        # Call the import hooks on the module being handled.

        module = sys.modules[fullname]
        _notify_import_hooks(fullname, module)

        return module

site module

site — Site-specific configuration hook

在python程序运行前,python环境初始化过程中自动调用。

完成工作,按照顺序为:

  1. 将sys.prefix 、sys.exec_prefix 和 lib/pythonX.Y/site-packages 合成module的search path.。加入sys.path。eg: /home/jay/env/tornado/lib/python2.7/site-packages

  2. 在添加的路径下寻找name.pth。 文件中描述了添加到sys.path的子文件夹路径。eg: 在我的/home/jay/env/tornado/lib/python2.7/site-packages下有一个newrelic.pth, 内容为"newrelic-2.46.0.37", 所以/home/jay/env/tornado/lib/python2.7/site-packages/newrelic-2.46.0.37/会被添加到sys.path。

  3. import sitecustomize . sitecustomize内部可以做任意的设置。

  4. import usercustomize。 usercustomize 内部做任意的设置。 但是usercustomize习惯上放在user python path 下, eg: /home/jay/.local/lib/python2.7/site-packages , 而且只有在site.ENABLE_USER_SITE == True时有效。

所以可以设置特殊的usercustomize.py文件, 在python代码执行之前,添加import hook。

boot_directory = os.path.dirname(__file__)
path = list(sys.path)
if boot_directory in path:
    del path[path.index(boot_directory)]

try:
    (file, pathname, description) = imp.find_module('sitecustomize', path)
except ImportError:
    pass
else:
    imp.load_module('sitecustomize', file, pathname, description)


from tornado_debug import agent

agent.initialize()

Written with StackEdit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment