3

我的一些代码似乎突然出现了一个错误。当我追踪它时,我发现inspect.getmodule在执行之前和之后使用相同(相同)的参数进行评估os.chdir会产生不同的结果。

(FWIW,我在 OS X 下运行 Python 2.7.3。)

我发现这种行为非常令人费解和困惑,以至于我不知道如何最好地修复这个错误。(换句话说,在了解行为的原因后,我能想到的任何解决方案都只是一个创可贴。)

下面的测试脚本说明了这种行为(当然,现实生活中的错误发生在更加现实和复杂的环境中):

import inspect
import os

def prn(line, mod):
    print ('getmodule called at line %2d; returned module: %-8s (id: %d)' %
           (line - 1, getattr(mod, '__name__', mod), id(mod)))

fr = inspect.currentframe()

mod = inspect.getmodule(fr) # line 10
prn(fr.f_lineno, mod)

mod = inspect.getmodule(fr) # line 13
prn(fr.f_lineno, mod)

os.chdir('subdir')

mod = inspect.getmodule(fr) # line 18
prn(fr.f_lineno, mod)

(注意:运行此代码需要在当前目录下立即有一个名为“subdir”的子目录。)

它的输出是:

getmodule called at line 10; returned module: __main__ (id: 4297636784)
getmodule called at line 13; returned module: __main__ (id: 4297636784)
getmodule called at line 18; returned module: None     (id: 4296513024)

请注意,尽管所有三个调用getmodule都具有相同的框架对象作为参数,但最后一个的结果与前两个的结果不同。(正如人们所期望的那样,前两次调用的结果是相同的。)

前两个调用和第三个调用的唯一区别是后者发生在运行之后os.chdir

任何有关正在发生的事情的见解将不胜感激。

4

2 回答 2

0

我认为这里的问题是您正在检查的模块也是__main__模块。如果您将示例代码放入另一个模块并将导入您的主模块,它工作正常。您在抓取框架后更改工作目录这一事实也对您没有任何好处。

如果您绝对需要一个模块也是应用程序,您可以手动将路径传递到inspect.getmodule

import os
import inspect

__filepath__ = os.path.join(os.getcwd(), __file__)

frame = inspect.currentframe()
os.chdir('subdir')
print inspect.getmodule(frame, _filename=__filepath__).__name__

但是,您确定需要像现在这样更改工作目录吗?在我编写 Python 的 8 年多的时间里,我不记得曾经在现实世界的代码中使用过它。

于 2012-08-20T03:21:25.877 回答
0

我尝试在 Windows 7 X64 上的 Idle Python 2.7.2 和 2.7.3 上运行代码,但是我无法重现这一点。我得到的只是:-

getmodule 在第 12 行调用;返回模块:main (id: 31281464)
getmodule 在第 15 行调用;返回模块:main (id: 31281464)
getmodule 在第 20 行调用;返回模块:main(id:31281464)

但是,我认为问题在于实施。正如 Python 文档中显而易见的那样:http: //docs.python.org/library/inspect.html#inspect.getmodule尝试猜测对象是在哪个模块中定义的。

我认为(这只是一个假设,因为我无法在我的系统上重现您的观察结果)在您更改当前目录之前,因为您在父目录中,模块显示为main,因此您收到 id:4297636784 . 但是,更改当前目录后,无法从新目录中引用该模块,因此返回新的 id: 4296513024 并以 None 作为模块,因为无法从新目录中引用主模块。

于 2012-08-18T20:07:06.180 回答