【问题标题】:Is there a way to get the name of the 'parent' module from an imported module?有没有办法从导入的模块中获取“父”模块的名称?
【发布时间】:2013-09-27 16:43:12
【问题描述】:

我很好奇是否可以访问其他模块导入的父模块的名称。

例如,如果我有一个模块 (moduleA) 并且父模块是模块 foo.py,它将被导入其中,moduleA 是否有可能知道 foo 的位置?

模块A

def print_parent_module(): 
    os.path.asbpath(#somehow access filename of parent module) 

foo.py

import moduleA 

print moduleA.print_parent_module()
>>> "foo.py"

【问题讨论】:

  • 一个模块可以被导入到许多其他模块中,所以不存在导入它的“那个”模块。
  • 我认为他的意思是问你是否可以编写一个函数来识别正在导入它的文件名(从外部模块)
  • @yuvi 是的!我解释得很糟糕,但这就是我要问的。
  • 可能,是的。一个好主意?当然不是。如果你问的意图是实际这样做,请不要这样做。
  • @ZackYoshyaro 尝试使用内置的__file__ 魔术方法来获取当前文件的名称。如os.path.abspath(__file__).

标签: python


【解决方案1】:

我遇到了类似的问题。你可以使用__name__:

parent_name = '.'.join(__name__.split('.')[:-1])

或者,如果您尝试直接访问该模块(不是 OP 的问题,而是相关的),请参阅我在 Is there a way to access parent modules in Python 中的回答

【讨论】:

  • 我需要这个答案。我试图在目录中的一个模块中为我的应用程序创建一个根记录器,并让该目录中的所有记录器传播到它。它不起作用,因为它的模块名称太具体,因此我需要模块的父目录。
  • 将 rsplit 用于(稍微)更快的代码,当然也更具可读性。我不会指望它在基准测试中更快,谁知道呢
【解决方案2】:

没有。导入的模块不保存任何形式的状态来存储与导入方式相关的数据。

我认为更好的问题是,您为什么还要这样做?您知道如果foo.py 确实是您的__main__,那么您可以轻松地从中获得名称foo.py(通过使用sys.argv)?而如果foo.py 是一个导入的模块,那么您显然在导入它时已经知道foo.py 的名称及其位置等。

【讨论】:

  • 我敢肯定,这似乎有点令人费解,但想要这样做的原因是为了以客户端代码不需要传递任何参数的方式装饰主函数给装饰者。我想出了一个简单的解决方法(将其作为答案发布在下面)。
【解决方案3】:

这是我用来存储父方法名称和变量的东西,以便稍后在类中使用装饰器调用。

import inspect
from functools import wraps

def set_reuse_vars(method):
    @wraps(method)
    def _impl(self, *method_args, **method_kwargs):
        func_current = inspect.currentframe()
        self.recall_func = dict()
        self.recall_func['method_kwargs'] = func_current.f_locals['method_kwargs']
        self.recall_func['method_name'] = func_current.f_locals['method'].__name__
        return method(self, *method_args, **method_kwargs)
    return _impl

class APIData(object):

    def __init__(self):
        self.client = None
        self.response = None
        self.recall_func = None

    def get_next_page(self):
        # Takes a pageToken to return the next result
        get_func = getattr(self, self.recall_func['method_name'])
        self.recall_func['method_kwargs']['pageToken'] = self.response['nextPageToken']
        return get_func(**self.recall_func['method_kwargs'])

    @set_reuse_vars
    def search_list_by_keyword(self, **kwargs):

        self.response = self.client.search().list(
            **kwargs
        ).execute()

        return self.response

运行它的脚本。

api_data = APIData()


results = api_data.search_list_by_keyword(
                       part='snippet',
                       maxResults=25,
                       order='date')


print(results)

resultsTwo = api_data.get_next_page()

print(resultsTwo)

【讨论】:

    【解决方案4】:

    想通了!

    函数内部的一点 import 语句可以访问模块名称。

    模块A

    def print_module_name():
        import sys
        return sys.argv[0]
    

    然后,在“父”模块内部

    # foo.py
    import os 
    import moduleA
    
    if __name__ == '__main__':
        print os.path.split(moduleA.print_module_name())[-1]
    

    给予:

    >>> 'foo.py'
    

    【讨论】:

    • 这只是打印您正在运行的脚本的名称。它与进口无关。
    • @IsmailBadawi 好吧..这就是我的问题。如何获取另一个模块导入的父模块。这是这样做的。我在想我只是解释了我试图完成的工作非常糟糕.. :/
    • 但这不是这样做的。这是打印您正在运行的脚本的名称。如果你运行 foo.py,它导入 A,A 导入 B,那么B.print_module_name() 将返回 foo.py,而不是 A。
    • 可以想象这是您问题的解决方案。但是,这不是您所提问题的答案。
    • @IsmailBadawi,哦……我明白你现在在说什么了。我很抱歉。是的,我似乎很糟糕地解释了我的问题! “模块名称”是指“调用导入函数的脚本名称”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 2020-05-27
    相关资源
    最近更新 更多