Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中进行相对导入?_Python_Python Import_Python Module - Fatal编程技术网

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

如何在Python中进行相对导入?,python,python-import,python-module,Python,Python Import,Python Module,想象一下这个目录结构: app/ __init__.py sub1/ __init__.py mod1.py sub2/ __init__.py mod2.py 我正在编码mod1,我需要从mod2导入一些东西。我该怎么做 我尝试了从..sub2 import mod2导入,但得到了一个“在非包中尝试相对导入” 我搜索了一下,但只找到了“sys.pathmanipulation”黑客。难道没有干净的方法吗 编辑:我的所有\uu

想象一下这个目录结构:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py
我正在编码
mod1
,我需要从
mod2
导入一些东西。我该怎么做

我尝试了从..sub2 import mod2导入
,但得到了一个“在非包中尝试相对导入”

我搜索了一下,但只找到了“
sys.path
manipulation”黑客。难道没有干净的方法吗


编辑:我的所有
\uuuuu init\uuuuuuy.py
当前为空

Edit2:我之所以这么做是因为sub2包含跨子包共享的类(
sub1
subX
,等等)


Edit3:我所寻找的行为与(感谢John B)

中描述的行为相同,每个人似乎都想告诉你应该做什么,而不仅仅是回答问题

问题是,通过将mod1.py作为参数传递给解释器,您正在以“\uuuu main\uuuu”的形式运行模块

发件人:

相对导入使用模块的_name __属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“\uuuu main\uuuuu”),则将解析相对导入,就像模块是顶级模块一样,而不管模块在文件系统上的实际位置如何

在Python2.6中,他们添加了相对于主模块引用模块的功能。描述更改

更新:根据Nick Coghlan的说法,推荐的替代方案是使用-m开关在包内运行模块

main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  • 您可以运行
    python main.py
  • main.py
    does:
    import app.package\u a.module\u a
  • module_a.py
    does
    import app.package_b.module_b
  • 或者2或3可以使用:
    从app.package\u导入模块\u a

    只要PYTHONPATH中有
    应用程序
    ,这就行了
    main.py
    可以在任何地方

    因此,您需要编写一个
    setup.py
    来将整个应用程序包和子包复制(安装)到目标系统的python文件夹中,并将
    main.py
    复制到目标系统的脚本文件夹中

    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
    
    我用这个片段从路径导入模块,希望对

    在Python2.5中,可以使用
    from\uuuuuu future\uuuuuu import absolute\u import
    指令将导入的行为切换为绝对导入。这种绝对导入行为将成为未来版本(可能是Python 2.7)的默认行为。一旦默认为绝对导入,
    导入字符串
    将始终找到标准库的版本。建议用户尽可能多地使用绝对导入,因此最好在代码中开始从pkg导入字符串编写

    看一看。你可以

    from .mod1 import stuff
    
    “Guido将包内运行的脚本视为反模式”(已拒绝) )


    我花了很多时间试图找到一个解决方案,阅读了这里有关堆栈溢出的相关文章,并对自己说:“一定有更好的方法!”。看起来没有。

    不幸的是,这是一个sys.path hack,但它运行得很好

    我在另一层遇到了这个问题:我已经有一个指定名称的模块,但它是错误的模块

    我想做的是以下几点(我工作的模块是模块3):

    请注意,我已经安装了mymodule,但在我的安装中没有“mymodule1”

    我会得到一个ImportError,因为它试图从我安装的模块导入

    我尝试执行sys.path.append,但没有成功。工作的是一个系统路径.insert

    if __name__ == '__main__':
        sys.path.insert(0, '../..')
    
    有点像黑客,但都成功了!
    因此,请记住,如果您希望您的决定覆盖其他路径,那么您需要使用sys.path.insert(0,pathname)使其生效!这对我来说是一个非常令人沮丧的症结所在,很多人都说要在sys.path中使用“append”函数,但如果已经定义了一个模块(我发现它的行为非常奇怪)

    我发现将“PYTHONPATH”环境变量设置到顶部文件夹更容易:

    bash$ export PYTHONPATH=/PATH/TO/APP
    
    然后:


    当然,PYTHONPATH是“全局的”,但它还没有给我带来麻烦。

    除了John B所说的之外,设置
    \uuuu package\uuuuu
    变量应该会有所帮助,而不是更改
    \uu main\uuuuu
    ,这可能会搞糟其他事情。但就我所能测试的而言,它并没有完全按照它应该的方式工作

    我有同样的问题,PEP 328或366都不能完全解决问题,因为据我所知,在一天结束时,两者都需要将包头包含在
    sys.path


    我还应该提到,我没有找到如何格式化应该进入这些变量的字符串。是
    “包头.子文件夹.模块名”
    还是什么

    让我把这个放在这里作为我自己的参考。我知道这不是一个好的Python代码,但是我需要一个脚本用于我正在进行的项目,我想把脚本放在
    scripts
    目录中

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

    以下是适合我的解决方案:

    我以
    from..sub2 import mod2
    然后,如果我想运行
    mod1.py
    ,那么我将转到
    app
    的父目录,并使用python-m开关作为
    python-m app.sub1.mod1
    运行模块

    相对导入出现此问题的真正原因是,相对导入通过使用模块的
    \uuu name\uuu
    属性来工作。如果模块正在直接运行,则
    \uuuu name\uuuu
    设置为
    \uuuu main\uuuu
    ,并且它不包含任何有关包结构的信息。这就是python抱怨非包中的
    相对导入错误的原因

    因此,通过使用-m开关,您可以提供包
    import sub1.func1
    #...more import
    
    import os.path
    import sys
    sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
    
    main.py
    app/ ->
        __init__.py
        package_a/ ->
           __init__.py
           fun_a.py
        package_b/ ->
           __init__.py
           fun_b.py
    
    def print_a():
        print 'This is a function in dir package_a'
    
    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()
    
    from app.package_b import fun_b
    fun_b.print_b()
    
    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
    
    import imp
    
    foo = imp.load_source('module.name', '/path/to/file.py')
    foo.MyClass()
    
    import sys
    sys.path.insert(0, "../settings")
    
    
    try:
        from local_settings import *
    except ImportError:
        print('No Import')
    
    export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"