如何在Python中进行相对导入?

想象一下这个目录结构: python

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

我正在编码mod1 ,我须要从mod2导入一些东西。 我该怎么办? app

我尝试from ..sub2 import mod2尝试from ..sub2 import mod2但出现“未打包的相对尝试导入”。 测试

我四处搜寻,但只发现“ sys.path操纵”黑客。 有没有一种干净的方法? 编码


编辑:我全部的__init__.py当前为空 spa

Edit2:我正在尝试执行此操做,由于sub2包含跨子包( sub1subX等)共享的类。 code

Edit3:我要寻找的行为与PEP 366中描述的相同(感谢John B) ip


#1楼

def import_path(fullpath):
    """ 
    Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
    """
    path, filename = os.path.split(fullpath)
    filename, ext = os.path.splitext(filename)
    sys.path.append(path)
    module = __import__(filename)
    reload(module) # Might be out of date
    del sys.path[-1]
    return module

我正在使用此代码片断从路径导入模块,但愿对您有所帮助 ci


#2楼

除了John B所说的之外,设置__package__变量彷佛应该有所帮助,而不是更改__main__可能会搞砸其余事情。 可是据我测试,它并不能彻底正常工做。 字符串

我遇到了一样的问题,而据我所知,PEP 328或366都没法彻底解决问题,由于二者在一天结束时都须要将程序包的头包含在sys.pathget

我还要提到的是,我没有找到如何格式化应放入这些变量的字符串的格式。 是"package_head.subfolder.module_name"仍是什么?


#3楼

让我将其放在此处以供我本身参考。 我知道这不是很好的Python代码,可是我须要一个脚原本处理我正在从事的项目,因此我想将该脚本放在scripts目录中。

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

#4楼

这是对我有效的解决方案:

from ..sub2 import mod2进行相对from ..sub2 import mod2 ,而后,若是我想运行mod1.py则转到app的父目录,并使用python -m开关做为python -m app.sub1.mod1运行模块python -m app.sub1.mod1

相对导入发生此问题的真正缘由是,相对导入经过采用模块的__name__属性__name__ 。 若是模块直接运行,则__name__设置为__main__ ,而且不包含有关包结构的任何信息。 而且,这就是为何python抱怨relative import in non-package错误中的relative import in non-package

所以,经过使用-m开关,您能够将包结构信息提供给python,经过它能够成功解析相对导入。

在进行相对导入时,我屡次遇到此问题。 并且,在阅读了全部先前的答案以后,我仍然没法弄清楚如何解决此问题,而无需在全部文件中都放入样板代码。 (尽管有些评论确实颇有帮助,这要感谢@ncoghlan和@XiongChiamiov)

但愿这对正在解决相对进口问题的人有所帮助,由于经过PEP确实颇有趣。


#5楼

用示例解释nosklo's答案

注意:全部__init__.py文件均为空。

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app / package_a / fun_a.py

def print_a():
    print 'This is a function in dir package_a'

app / package_b / fun_b.py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

若是运行$ python main.py它将返回:

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a
  • main.py能够: from app.package_b import fun_b
  • fun_b.py from app.package_a.fun_a import print_a

所以,文件夹package_b中的文件使用了文件夹package_a中的文件,这就是您想要的。 对??

相关文章
相关标签/搜索