Python相对导入__

Python相对导入__,python,import,Python,Import,假设我有一个包含以下文件的模块包。一个空文件C:\codes\package\\uuuuu init\uuuuu.py和一些非普通文件: 一个位于C:\codes\package\first.py def f(): print 'a' def f(): print 'b' 另一个位于C:\codes\package\second.py def f(): print 'a' def f(): print 'b' 还有第三个文件:C:\codes\packag

假设我有一个包含以下文件的模块包。一个空文件
C:\codes\package\\uuuuu init\uuuuu.py
和一些非普通文件:

一个位于
C:\codes\package\first.py

def f():
    print 'a'
def f():
    print 'b'
另一个位于
C:\codes\package\second.py

def f():
    print 'a'
def f():
    print 'b'
还有第三个文件:
C:\codes\package\general.py
,其中包含以下代码

def myPrint(module_name):
    module = __import__(module_name)
    module.f()

if __name__ == '__main__':
    myPrint('first')
    myPrint('second')
当我运行后一个文件时,一切正常。但是,如果我尝试执行包含

if __name__ == '__main__':
    from package import general
    general.myPrint('first')
    general.myPrint('second')

我得到导入错误
ImportError:没有名为first的模块
。如何解决此问题?

首先,我怀疑您忘记了,您有一个文件
package\\uuu init\uuuu.py
,它使
package
成为一个包。否则,来自package import general的
将不起作用

第二种情况与第一种情况不同,因为您在一个包中。从包内部,您不会先执行
import
,而是先执行
import.first
。后面描述了与后者等效的方法,即添加
level=1
作为参数,或者(但我不确定)将
。首先
放入字符串中,并将
level
设置为
-1
(如果它不是默认值,文档中不清楚)

此外,您必须至少提供
globals()
,因此右行是

module = __import__(module_name, globals(), level=1)

我找到了这个解决方案。

首先,我怀疑您忘记了,您有一个文件
package\\uuu init\uuuu.py
,它使
package
成为一个包。否则,来自package import general的
将不起作用

第二种情况与第一种情况不同,因为您在一个包中。从包内部,您不会先执行
import
,而是先执行
import.first
。后面描述了与后者等效的方法,即添加
level=1
作为参数,或者(但我不确定)将
。首先
放入字符串中,并将
level
设置为
-1
(如果它不是默认值,文档中不清楚)

此外,您必须至少提供
globals()
,因此右行是

module = __import__(module_name, globals(), level=1)

我找到了这个解决方案。

在您的情况下,您应该从
软件包
导入您的
模块名称
。使用
fromlist
参数:

getattr(__import__("package", fromlist=[module_name]), module_name)

在您的情况下,您应该从
软件包
导入您的
模块名称
。使用
fromlist
参数:

getattr(__import__("package", fromlist=[module_name]), module_name)

假设您使用的是Python3,这只是因为该版本放弃了对的支持。使用Python2,它会工作得很好

因此,您需要在
C:\codes\package\general.py
中使用相对导入,这将导致对它的错误调用,或者将包添加到路径中。有点脏,但工作黑客会:

def myPrint(module_name):
    pkg = os.path.dirname(__file__)
    sys.path.insert(0, pkg)
    try:
        module = __import__(module_name)
    except:
        raise
    finally:
        sys.path.remove(pkg)
    module.f()

也许您可以使用该模块实现更清晰的实现。

假设您使用的是Python 3,这只是因为该版本放弃了对的支持。使用Python2,它会工作得很好

因此,您需要在
C:\codes\package\general.py
中使用相对导入,这将导致对它的错误调用,或者将包添加到路径中。有点脏,但工作黑客会:

def myPrint(module_name):
    pkg = os.path.dirname(__file__)
    sys.path.insert(0, pkg)
    try:
        module = __import__(module_name)
    except:
        raise
    finally:
        sys.path.remove(pkg)
    module.f()

也许你可以用这个模块实现一个更干净的实现。

我不认为OP忘记添加
\uu init\uuuuuuuy.py
,因为
来自package import general
适用于他,因为我说过:他只是忘了提到这个文件。@Danil:正如Glglglgl正确地注意到的,我确实添加了它,但忘了提及。谢谢你的回答,因此,在导入中,我将执行
\uu导入('..+moduleName)
?@Ulysses尝试一下-但可能是
\uu导入(moduleName,级别=1)
会更好。我不认为OP忘了添加
\uuu init\uuuuuuuuy.py
,因为包导入通用
中的
对他有效,因为我说过:他只是忘了提到文件。@Danil:正如GLGLGLGL正确地注意到的,我确实添加了它,但忘了提及。谢谢你的回答,所以在导入中我将执行
\uuu导入('..+moduleName)
?@Ulysses尝试一下-但可能是
\uuuu导入(moduleName,级别=1)
会更好。如果有人重命名包?最好是进行相对导入。@glglglgl我不确定是否可以在
\uuuuuuuuu导入中使用相对路径,如果有人重命名包?最好是进行相对导入。@glglglgl我不确定是否可以在
\uuuu导入中使用相对路径__