我有一个模块private class ExtendedWebClient : System.Net.WebClient
{
public long ContentLength { get; set; }
public ExtendedWebClient(long contentLength)
{
ContentLength = contentLength;
}
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
System.Net.HttpWebRequest hwr = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
hwr.AllowWriteStreamBuffering = false; //do not load the whole file into RAM
hwr.ContentLength = ContentLength;
return (System.Net.WebRequest)hwr;
}
}
,其中包含以下代码:
some_module.py
现在,在名为def testf():
print(os.listdir())
的文件中,我有以下代码:
test.py
但是执行test.py会给我import os
from some_module import testf
testf()
。我已在NameError: name 'os' is not defined
中导入os
,test.py
位于testf
的命名空间中。那么为什么会出现这种错误?
答案 0 :(得分:4)
import
与包含文件内容不同,就像您直接键入import
语句一样。如果你来自C背景,你可能认为它是这样工作的,#include
预处理器指令就是这样做的,但Python是不同的。
Python中的import
语句读取正在导入的文件的内容并在其自己的单独上下文中对其进行评估 - 因此,在您的示例中,some_module.py
中的代码无法访问或了解test.py
或任何其他文件中存在的任何内容。它可以说是一个“空白的板岩”。如果some_module.py
的代码想要访问os
模块,则必须将其导入some_module.py
的顶部。
在Python中导入模块时,它将成为对象。也就是说,当你写
import some_module
Python所做的第一件事就是创建一个类型为module
的新对象来表示正在导入的模块。当解释器遍历some_module.py
中的代码时,它会将该文件中定义的任何变量,函数,类等分配为此新模块对象的属性。因此,在您的示例中,模块对象将具有一个属性testf
。当函数testf
中的代码想要访问变量os
时,它会查看函数本身(本地范围)并看到os
未在那里定义,因此它会查看testf
所属的模块对象的属性(这是“全局”范围,尽管它不是真正的全局范围)。在您的示例中,它不会在那里看到os
,因此您会收到错误消息。如果你添加
import os
到some_module.py
,然后会在名称os
下创建模块的属性,您的代码将找到它所需的内容。
您可能也对我编写的其他一些答案感兴趣,这些答案可能有助于您理解Python的import
声明:
答案 1 :(得分:2)
名称 testf
位于test
的名称空间中。 testf
功能的内容仍在some_module
中,无法访问test
中的任何内容。
如果您的代码需要模块,则需要将该模块导入该代码所在的同一文件中。导入模块只会将其导入到导入模块的文件中。 (在不同的文件中多次导入同一模块,不会产生有意义的性能损失;模块的实际加载只发生一次,后来导入的同一模块只是引用已经导入的模块。)
答案 2 :(得分:2)
导入模块会将其名称添加为当前范围的属性。由于不同的模块具有独立的范围, obj.getUsrCnt = function getUsrCnt(callback) {
var promise = new Promise(function(resolve, reject) {
connection.acquire(function(err, con) {
if(err) {
return reject(err);
}
con.query(query1, function(err, result) {
con.release();
resolve(result[0].some);
})
});
});
return promise;
}
中的任何代码都不能使用returnedPromise.then(function(data) {
//this data is what we got from resolve
}).catch(function(err) {
//this err is what we got from reject
});
(已执行的脚本)中的名称而不先导入它。