Python 类位于sys.modules中,但无法使用。为什么?

Python 类位于sys.modules中,但无法使用。为什么?,python,Python,我有一个文件MySQL.py,其中包含一个类MySQL,定义如下: class MySQL: ... all stuff that is not important here 在同一目录下的另一个文件(test.py)中,我对这个MySQL类进行了条件加载。通过这个条件加载,我的意思是,如果它还没有被加载,我就加载它。为了检查它,我使用如下类似的sys.modules: print("MySQL" not in sys.modules) if "MySQL" not in sys.mo

我有一个文件
MySQL.py
,其中包含一个类
MySQL
,定义如下:

class MySQL:
    ... all stuff that is not important here
在同一目录下的另一个文件(test.py)中,我对这个
MySQL
类进行了条件加载。通过这个条件加载,我的意思是,如果它还没有被加载,我就加载它。为了检查它,我使用如下类似的
sys.modules

print("MySQL" not in sys.modules)
if "MySQL" not in sys.modules:
    from MySQL import MySQL
    print("Loaded it")
    print("MySQL" not in sys.modules)
return MySQL()
如您所见,我有一些用于调试的
print
。这是我在控制台中运行此文件时得到的结果:

$ python3 test.py
True
Loaded it
False
Traceback ...
...
UnboundLocalError: local variable 'MySQL' referenced before assignment
这真的很有趣,因为在控制台中我们看到,一开始模块没有加载(
print(“MySQL”不在sys.modules中)
=>
True
),然后我们看到它被加载了,但最后由于一些疯狂的原因,
Python
没有看到这个类。另外,我应该补充一点,如果我在文件的最开始导入(在所有其他代码之前,那么一切都正常)

编辑


我想,我明白了,所有问题的全部原因是我导入的方式将我的类放到了sys.modules,但同时它将它放到了函数的本地名称空间,而不是模块的全局名称空间。就是这样。

您的代码不起作用,因为如果以前加载了
MySQL
模块,则您没有导入该类,因此在最后一行调用
MySQL()
的尝试无法起作用

更好的方法是无条件地进行导入。加载模块后,Python会缓存该模块(这是
sys.modules
的全部目的),因此,如果您多次导入该模块,其中的重量级代码仍将只运行一次


这就是说,如果你的模块在顶层做了很多事情,这可能是一个糟糕设计的标志。也许您应该将部分或全部对象创建或函数中的任何内容移动到某个位置,并在适当的时间调用它。

为什么不从一开始就导入,使一切正常,就像您应该做的那样?这是函数中
test.py
中的代码吗?如果是这样,您还没有第二次导入MySQL,因此它不存在于本地或全局命名空间中,从而导致了问题。您为什么要进行“条件加载”?如果它已经加载,那么
import
就变成了
sys.modules
@Anand.S Kumar中的一个简单查找。是的,代码在一个函数中,返回语句也在这个函数中不幸的是,你的问题是。您已经有了干净的工作代码-除非/直到有必要,否则不要弄乱它。“也许您应该将部分或全部对象创建或函数中的任何内容移动到某个位置,并在适当的时间调用它。”-这实际上是我在工厂类中所做的,不做任何事情,但创建不同类的实例。但是,如果我们在实例化特定类之前放入
import
语句,您认为这是一个糟糕的设计吗?如果我们在顶部导入所有可能的类,但在运行时只使用一个类,这会是一个好的设计吗?@Jacobian-正如PEP8所说,是的,简单地将导入放在顶部是一个好的设计。我无法理解这种想法,“如果MySQL模块之前已经加载,…,调用MySQL()的尝试最后一行中的“”无法工作。“。为什么它不能工作,如果它已加载?@TigerhawkT3。我认为应该有另一个好的设计模式,即只加载/导入您实际使用的代码。@Jacobian:import语句做两件事:在必要时加载模块(只加载一次,然后缓存),并将请求的名称放入命名空间。如果在名称空间中没有获得
MySQL
,则不能调用它。