在 python 类中导入模块
Posted
技术标签:
【中文标题】在 python 类中导入模块【英文标题】:Importing modules inside python class 【发布时间】:2011-10-15 05:53:12 【问题描述】:我目前正在编写一个需要os
、stat
和其他一些的类。
在我的班级中导入这些模块的最佳方式是什么?
我正在考虑其他人何时会使用它,我希望“依赖”模块已经存在 在类实例化时导入。
现在我在我的方法中导入它们,但也许有更好的解决方案。
【问题讨论】:
【参考方案1】:This(搜索“Imports”部分)官方文件指出,import
s 通常应该放在源文件的顶部。除了特殊情况,我会遵守这条规则。
【讨论】:
这是一种特殊情况。如果用户没有安装特定的库,您希望优雅地失败。假设你有一个脚本可以做很多事情,并且可以选择将日志推送到日志服务器。可能未安装日志服务器的库。如果是这种情况,您希望脚本仍然运行。如果用户配置了日志记录,我们可以打印错误然后退出。但是如果用户没有配置日志记录,脚本应该仍然能够在没有日志记录的情况下运行。将导入放在脚本顶部意味着如果没有安装库,它将一直失败。【参考方案2】:PEP 8 导入:
导入总是放在文件的顶部,就在任何模块之后 cmets 和 docstrings,以及模块全局变量和常量之前。
这使得查看手头文件使用的所有模块变得容易,并且避免了在多个地方使用模块时必须在多个地方复制导入。其他一切(例如函数/方法级别的导入)都应该是一个绝对例外,并且需要很好地证明其合理性。
【讨论】:
这适用于无条件导入。如果您只想在实例化该类时导入它们,显然这不适用。 @agf:虽然很少有条件导入的理由。特别是对于 OP 使用的模块,这些可能已经被实现使用(尝试python -c "import sys; print sys.modules.keys()"
)。【参考方案3】:
如果您的模块将始终导入另一个模块,请始终将其作为PEP 8 放在顶部,其他答案表明。此外,正如@delnan 在评论中提到的那样,sys
、os
等无论如何都在使用,因此在全球范围内导入它们并没有什么坏处。
但是,如果您真的只需要在某些运行时条件下使用模块,那么条件导入并没有什么问题。
如果您只想在类已定义时导入它们,例如该类位于条件块或其他类或方法中,您可以执行以下操作:
condition = True
if condition:
class C(object):
os = __import__('os')
def __init__(self):
print self.os.listdir
C.os
c = C()
如果您只想在类实例化时导入它,请在__new__
或__init__
中进行。
【讨论】:
如果我在一个方法中导入一个模块(例如__init__
),如果我创建多个实例,它不会多次导入该模块吗?因此,与全局导入相比,它会影响性能吗?
在导入之后不应该是(),而不是[]?当我使用括号时,我收到错误“TypeError:'builtin_function_or_method' object has no attribute '__getitem'”。将其更改为 () 后,它可以工作,但是我必须在导入的模块前面加上类的名称,即使在类中使用导入的模块,我也不想这样做。有什么办法吗?
@Samuel:感谢您的更正,我修复了导入。如果您希望导入的对象全局可用,只需使用普通的import
语句即可。不过,这对于条件导入来说并不是一个好主意,因为您可以在条件外部设置代码,该条件仅在具有导入的条件分支首先执行时才有效。如果像上面那样使用__import__
,就可以避免为对象创建全局名称。
我明白了。我想要一个全局名称,但我想要一个条件导入。我正在根据用户选择的输出格式导入 xlsxwriter 模块,所以我并不总是想导入它。谢谢你的帮助!这告诉我什么是可能的以及如何去做。【参考方案4】:
import sys
from importlib import import_module
class Foo():
def __init__(self):
if self.condition:
self.importedModule = import_module('moduleName')
if 'moduleName' in sys.modules:
self.importedModule.callFunction(params)
#or
if self.condition:
self.importedModule.callFunction(params)
【讨论】:
以上是关于在 python 类中导入模块的主要内容,如果未能解决你的问题,请参考以下文章