【问题标题】:How to list imported modules?如何列出导入的模块?
【发布时间】:2011-06-18 23:45:18
【问题描述】:

如何枚举所有导入的模块?

例如我想从这段代码中得到['os', 'sys']

import os
import sys

【问题讨论】:

  • 我认为这在原生 Python 中是不可能的,但之前的这个问题可能会有所帮助:stackoverflow.com/questions/2572582/…
  • 有时(例如:ipython --pylab)python 解释器会在加载预定义模块的情况下启动。问题仍然存在,如何知道使用的别名 o_O
  • 对于那些有兴趣显示所有模块及其版本号的列表作为可重复性的小衡量标准的人,请参阅此问题的答案stackoverflow.com/questions/20703975/…

标签: python


【解决方案1】:

这里有很多扭曲的答案,其中一些在最新的 Python 3.10 上无法正常工作。获取脚本的完全导入模块而不是内部 __builtins__sub-imports 的最佳解决方案是使用以下方法:

# import os, sys, time, rlcompleter, readline
from types import ModuleType as MT
all = [k for k,v in globals().items() if type(v) is MT and not k.startswith('__')]
", ".join(all)

# 'os, sys, time, rlcompleter, readline'

上面的结果是受@marcin上面的答案启发的,它基本上是把所有模块全局变量结合起来:

# import os, sys, time, rlcompleter, readline
modulenames = set(sys.modules) & set(globals())
allmodules = [sys.modules[name] for name in modulenames]
for i in allmodules: print (' {}\n'.format(i))

#<module 'time' (built-in)>
#<module 'os' from 'C:\\Python310\\lib\\os.py'>
#<module 'sys' (built-in)>
#<module 'readline' from 'C:\\Python310\\lib\\site-packages\\readline.py'>
#<module 'rlcompleter' from 'C:\\Python310\\lib\\rlcompleter.py'>

还要注意 order 的导入如何也反映在 第一个 解决方案中,但不是在最后一个解决方案中。然而,模块路径也在 2nd 解决方案中给出,这对调试很有用。

PS。不确定我在这里使用了正确的词汇,所以如果我需要更正,请发表评论。

【讨论】:

    【解决方案2】:

    如果您想从脚本外部执行此操作:

    Python 2

    from modulefinder import ModuleFinder
    finder = ModuleFinder()
    finder.run_script("myscript.py")
    for name, mod in finder.modules.iteritems():
        print name
    

    Python 3

    from modulefinder import ModuleFinder
    finder = ModuleFinder()
    finder.run_script("myscript.py")
    for name, mod in finder.modules.items():
        print(name)
    

    这将打印 myscript.py 加载的所有模块。

    【讨论】:

    • 对于 Python 3,将 .iteritems() 更改为 .items() 并为 print 语句加上括号
    • 注意:处理命名空间时会崩溃:bugs.python.org/issue40350
    • 这个片段本身在我的机器上有 204 个依赖项......这是奇怪的还是预期的?
    【解决方案3】:

    找到sys.modulesglobals 的交集:

    import sys
    modulenames = set(sys.modules) & set(globals())
    allmodules = [sys.modules[name] for name in modulenames]
    

    【讨论】:

    • 也许在这里改用frozenset? - 这是我的 1 班轮:frozenset(imap(lambda name: modules[name], frozenset(modules) &amp; frozenset(globals())))
    • 上述解决方案不会提取使用from 命令导入的模块。例如考虑from scipy.stats import norm。这并没有告诉我 norm 模块已导入。如何将其纳入其中?
    • @Ujjwal 好吧,这些模块没有被导入,只是它们的组件。如果您需要一切,只需使用 sys.modules。
    【解决方案4】:

    假设您已导入数学并重新:

    >>import math,re
    

    现在来看看同样的用法

    >>print(dir())
    

    如果你在导入前和导入后运行它,可以看出区别。

    【讨论】:

    • 结果仅包括标准库模块,例如。 mathresys,这符合 OP 的示例。但是它无法包含所有导入的模块,例如。 myapp.client.
    【解决方案5】:

    从@Lila 窃取(由于没有格式化无法发表评论),这也显示了模块的/path/:

    #!/usr/bin/env python
    import sys
    from modulefinder import ModuleFinder
    finder = ModuleFinder()
    # Pass the name of the python file of interest
    finder.run_script(sys.argv[1])
    # This is what's different from @Lila's script
    finder.report()
    

    产生:

    Name                      File
    ----                      ----
    
    ...
    m token                     /opt/rh/rh-python35/root/usr/lib64/python3.5/token.py
    m tokenize                  /opt/rh/rh-python35/root/usr/lib64/python3.5/tokenize.py
    m traceback                 /opt/rh/rh-python35/root/usr/lib64/python3.5/traceback.py
    ...
    

    .. 适合 grepping 或你有什么。请注意,它很长!

    【讨论】:

      【解决方案6】:

      我喜欢在这种情况下使用列表推导:

      >>> [w for w in dir() if w == 'datetime' or w == 'sqlite3']
      ['datetime', 'sqlite3']
      
      # To count modules of interest...
      >>> count = [w for w in dir() if w == 'datetime' or w == 'sqlite3']
      >>> len(count)
      2
      
      # To count all installed modules...
      >>> count = dir()
      >>> len(count)
      

      【讨论】:

        【解决方案7】:

        此代码列出了您的模块导入的模块:

        import sys
        before = [str(m) for m in sys.modules]
        import my_module
        after = [str(m) for m in sys.modules]
        print [m for m in after if not m in before]
        

        如果您想知道在新系统上安装哪些外部模块来运行您的代码,它应该很有用,而无需一次又一次地尝试。

        它不会列出 sys 模块或从它导入的模块。

        【讨论】:

          【解决方案8】:
          import sys
          sys.modules.keys()
          

          仅获取当前模块的所有导入的近似方法是检查 globals() 的模块:

          import types
          def imports():
              for name, val in globals().items():
                  if isinstance(val, types.ModuleType):
                      yield val.__name__
          

          这不会返回本地导入,或像 from x import y 这样的非模块导入。请注意,这将返回val.__name__,因此如果您使用import module as alias,您将获得原始模块名称;如果您想要别名,请改为使用名称。

          【讨论】:

          • 或者你可以找到 sys.modules 和 globals 的交集,根本不做类型测试。
          • 这是在重新定义导入模块的名称时返回完整模块名称的唯一解决方案。例如,如果您执行import numpy as np,这将返回numpy,而其他两个建议将返回np
          • 如果您出于某种原因需要模块名称和别名,可以在 name 变量中使用。因此,要生成字符串 import numpy as np,请执行类似 'import %s as %s' % (val.__name__, name) 之类的操作,现在是 yield 语句。
          【解决方案9】:

          它实际上工作得很好:

          import sys
          mods = [m.__name__ for m in sys.modules.values() if m]
          

          这将创建一个带有可导入模块名称的列表。

          【讨论】:

          • 这并不能真正回答问题。
          【解决方案10】:
          print [key for key in locals().keys()
                 if isinstance(locals()[key], type(sys)) and not key.startswith('__')]
          

          【讨论】:

            猜你喜欢
            • 2020-01-10
            • 2015-09-18
            • 2016-11-11
            • 2019-10-27
            • 1970-01-01
            • 2020-12-06
            • 1970-01-01
            • 2021-09-22
            • 2018-03-31
            相关资源
            最近更新 更多