2012-01-21 52 views
51

如何导入驻留在父目录中的模块(python文件)?从父目录导入脚本

这两个目录都有一个__init__.py文件,但我仍然无法从父目录中导入文件?

在此文件夹布局,脚本B试图导入脚本A:

Folder A: 
    __init__.py 
    Script A: 
    Folder B: 
    __init__.py 
    Script B(attempting to import Script A) 

在脚本B下面的代码不起作用:

import ../scriptA.py # I get a compile error saying the "." is invalid 
+0

不是完全回答你的问题,但是如果你运行文件夹A中的__init__.py,并尝试导入文件夹B或脚本B,脚本A将成功导入脚本B中。 – Michael0x2a

回答

52

不会导入在Python脚本导入模块。一些python模块也是可以直接运行的脚本(它们在模块级别执行一些有用的工作)。

通常,最好使用绝对导入而不是相对导入。

toplevel_package/ 
├── __init__.py 
├── moduleA.py 
└── subpackage 
    ├── __init__.py 
    └── moduleB.py 

moduleB

from toplevel_package import moduleA 

如果你想运行moduleB.py作为脚本,然后请确保toplevel_package父目录是在sys.path

+5

为什么不应该在这种情况下使用sys路径“黑客”?如果没有它们,Python很难做到你想要的东西。这里的缺点究竟是什么? –

+2

@BT *«'sys.path.append(path_to_parent)'»*不应该是如何修复的答案*“”import ../scriptA.py#我得到一个编译错误,说“。”无效““* 题。有些情况下可以改变'sys.path',例如,如果python本身已经完成了它或者一个三方模块,它可以正确处理所有的角落案例,例如'import autopath; autopath.add_toplevel_to_syspath()',它会自动将toplevel_package的父目录添加到'sys.path'中,以允许直接执行内部模块作为脚本(或在REPL中)从任何目录执行,而不进行正确的PYTHONPATH或(virtualenv)安装。 – jfs

+0

@JFSebastian是否有某种提议让我们明确说明整个项目的主文件夹或包是什么,这样我们就不必关心在sys.path中添加父目录了我们可以将子模块也作为主要文件或脚本运行?我有一个项目,我真的需要将脚本作为主要模块或作为模块运行,这是导入的,但我需要做大量的hack操作,为'sys.path'添加路径以使它们在两种情况下都能正常工作。在virtualenv工作或使用setuptools工作?我真的很苦恼... – nbro

24

docs

from .. import scriptA 

您可以在包中执行此操作,但不能在您直接运行的脚本中执行此操作。从上面的链接:

Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application should always use absolute imports.

如果您创建导入A.B.B的脚本,您将不会收到ValueError。

+15

ValueError:试图在非包中尝试相对导入 – jgritty

+3

@jgritty,那是因为你正在使用直接运行的脚本。 –

+2

是的,你是对的。它会工作,如果你调用一个脚本,然后导入脚本B. – jgritty

4

如果您想直接运行脚本,你可以:

  1. 添加FolderA的路径环境变量(PYTHONPATH)。
  2. 在脚本中添加到sys.path的路径。

然后:

import module_you_wanted