os.chdir之后inspect.getmodule的结果发生了变化

时间:2012-08-18 13:43:03

标签: python module inspect chdir

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

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

我发现这种行为令人费解和困惑,我不知道如何最好地修复bug。 (换句话说,通过理解行为的原因,我能想到的任何解决方案都只是一种创可贴。)

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

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之后发生。

任何有关正在发生的事情的见解都将受到赞赏。

2 个答案:

答案 0 :(得分:0)

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

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

但是,我认为问题在于实施。正如Python文档中所示:http://docs.python.org/library/inspect.html#inspect.getmodule尝试猜测对象的定义位置。

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

答案 1 :(得分: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年多的时间里,我不记得曾经在现实世界的代码中使用它。