Welcome, guest | Sign In | My Account | Store | Cart

Sometimes we want to have a module initialized in different ways. This function, getimporter(), while placed inside a module X, allow you to initialize module X according to the module (properties) that is importing X.

Python, 73 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def getimporter():
    ''' Placing this inside a module X, return a 7-tuple representing
        the module that is importing X:

        ( modulename,  frame, filepath, lineno, name, codetext, somenumber )

        The items starting from the 2nd one are the 6-tuple frame info.
        For example, when a file 'importer.py' imports a module 'imported.py'
        in which this function "getimporter" is placed, getimporter will
        report:

        ('importer',
        <frame object at 0x014C7A80>, 'E:\\py\\src\\importer.py',
        2, 'importer', ['import imported\n'], 0)        

        This function is useful when users intend to do different things
        with a module X according to the properties/attributes of a module
        that is importing X. That is, an 'importer-specific 
        module initialization'.
        
        Usage:
        ------
        
        importer = getimporter()
        if importer[0] == 'mytools': (do something)
        else: (do something else)

        or, it might be helpful in avoiding recursive importing:

        importer = getimporter()
        if importer[0] == 'mytools': import some module
        else: import another module
        
        How it works:
        -------------

        The inspect.stack() returns a list of 6-tuples for the execution
        stack. Each 6-tuple is a frame info:

        (frame, filepath, lineno, name, codetext, somenumber)

        When an inspect.stack() is placed in a module X, and X is
        imported by Y, then one of the 6-tuples will look like:        
        
        info= (<frame object at 0x00BA04A0>, 'C:\\pan\\py\\src\\Y.py',
        2, '?', ['import X\n'], 0)

        in which the 1st item of the info[4] is a string starting with
        either 'import X' or 'from X' or ' import pantools.X' or
        ' from pantools.X'. This will serve as the criteria for finding Y.
    '''

    # First find the name of module containing this (getimporter)
    
    frame, path, lineno, name, codetext, somenumber= inspect.stack()[1]
    module =  os.path.split(path)[1].split('.')[0]   # get the module name only
    
    # Then get the calling stack       
    for frame, file, lineno, name, codetext, somenumber in inspect.stack():
        codetexts = codetext[0].split() # The first will be either 'from' or 'import'

        # Possibilities:
        #
        # import X
        # form   X import blah
        # import tools.X
        # from   tools.X import blah
        
        if codetexts[0] in ('from', 'import') and \
           codetexts[1].split('.')[-1] == module:
            name = os.path.split(file)[1].split('.')[0]
            return name, frame, file, lineno, name, codetext, somenumber
    return (None, )

For a little demo, we setup 4 small files:

(1) imported.py: A module to be imported. getimporter will return who imports it.

import inspect, os importee= getimporter()[0]

(2) A.py: A module to import the imported

import imported print 'I am A. I import imported. it reports:' print 'I am imported by:', imported.importee

(3) B.py: A module to import the imported

import imported print 'I am B. I import imported. it reports:' print 'I am imported by:', imported.importee

(4) C.py: A module to import B that in turns imports the imported

import B print 'I am C. I import B. it reports:' print 'I am imported by:', B.imported.importee

Now some executions:

python A.py I am A. I import imported. it reports: I am imported by: A

python B.py I am B. I import imported. it reports: I am imported by: B

python C.py I am B. I import imported. it reports: I am imported by: B I am C. I import B. it reports: I am imported by: B

Created by runsun pan on Fri, 3 Feb 2006 (PSF)
Python recipes (4591)
runsun pan's recipes (5)

Required Modules

  • (none specified)

Other Information and Tasks