2011-12-07 41 views
4

我需要通过文件路径导入python模块(例如,“/some/path/to/module.py”),只在运行时知道并忽略任何.pyc文件存在。强制python从文件路径动态加载模块时忽略pyc文件

这个previous question建议使用imp.load_module作为解决方案,但是这种方法如果存在的话也会使用.pyc版本。

importme.py

SOME_SETTING = 4 

main.py:

import imp 
if __name__ == '__main__': 
    name = 'importme' 
    openfile, pathname, description = imp.find_module(name) 
    module = imp.load_module(name, openfile, pathname, description) 
    openfile.close() 
    print module 

执行两次,.pyc文件首先调用后使用:

$ python main.py 
<module 'importme' from '/Users/dbryant/temp/pyc/importme.py'> 

$ python main.py 
<module 'importme' from '/Users/dbryant/temp/pyc/importme.pyc'> 

Unfortun ately,imp.load_source具有相同的行为(从文档):

注意,如果正确匹配字节编译的文件(后缀为.pyc文件 或.pyo)存在,它将用来代替解析给定的来源 文件。

制作包含脚本的目录只读的是,我所知道的(防止产生.pyc文件摆在首位),但如果可能的话,我宁愿避免它的唯一解决方案。

(注:使用Python 2.7)

+1

为什么要防止使用pyc文件?它只会使用pyc文件,如果它与py相同。如果你改变py,它会重新编译pyc。 – Falmarri

+0

@Falmarri这很复杂。它与不同类型的机器访问相同的一组python文件有关,它们似乎产生了相同源代码的不兼容的字节汇编(例如,机器A生成的pyc不能被机器B读取,导致机器B无法动态地导入模块);是的,所有机器都使用解释器二进制。 – awesomo

+0

不同机器编写不同字节码的唯一原因是它们运行不同版本的解释器。 – limscoder

回答

0

如何使用含蟒蛇来源,而不是zip文件:

import sys 
sys.path.insert("package.zip") 
+0

有趣,但对我的用例来说效果并不理想。我动态加载的模块是设置文件,需要易于阅读和编辑。 – awesomo

+2

你也可以看看使用PYTHONDONTWRITEBYTECODE环境变量。 –

+0

好点。这也会起作用,但唯一导致问题的pyc文件是那些用'imp'动态加载的文件,我希望能够在所有其他东西可用时仍然使用字节码版本。 – awesomo

0

你可以标记包含.py文件为只读的目录。

+0

是的,我知道(请参阅问题的底部),但这并不是真正解决问题,而且非常不方便,因为我确实需要仍然写入包含日志,输出等的目录。 – awesomo

+0

我不知道你确切的情况是,但我通常会尽量避免将数据写入包含代码的同一目录。 – limscoder

+0

我原则上同意,但在这种情况下Python设置文件模糊了数据和代码之间的界限(例如在Django中很常见的做法) – awesomo

2

load_source做正确的事情对我来说,即

dir, name = os.path.split(path) 
mod = imp.load_source(name, path) 

使用即使PYC文件可在变异的.py - 名.py下python3结束。显而易见的解决方案显然是在加载文件之前删除所有.pyc文件 - 尽管运行多个程序实例,但竞态条件可能会成为问题。

另一种可能性:Iirc可以让Python从内存中解释文件 - 即使用正常的文件API加载文件,然后编译内存中的变体。例如:

path = "some Filepath.py" 
with open(path, "r", encoding="utf-8") as file: 
    data = file.read() 
exec(compile(data, "<string>", "exec")) # fair use of exec, that's a first! 
+0

不错,我甚至没有考虑执行设置文件/模块内容。这对我来说也是一个可行的解决方案。 – awesomo