【问题标题】:change in import handling / modules from python2 to python3?导入处理/模块从 python2 到 python3 的变化?
【发布时间】:2013-11-07 19:43:08
【问题描述】:

我试图遵循this previous question 中显示的与 SQLAlchemy 相关的设计模式,并打算在多个文件之间共享一个公共 Base 实例。代码与 python2 和 python3 完全相同。

但是,当我在一个模块(称为模型)中移动文件 a.py、b.py、c.py 和 base.py 并添加必要的 __init__.py 文件时,它继续在 python2 上工作,但随后在 python3 上产生错误(详情如下)。

我有以下文件:

模型/base.py

​​>
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

模型/a.py

​​>
from sqlalchemy import *
from base import Base
from sqlalchemy.orm import relationship

class A(Base):
    __tablename__ = "A"
    id  = Column(Integer, primary_key=True)
    Bs  = relationship("B", backref="A.id")
    Cs  = relationship("C", backref="A.id")

模型/b.py

​​>
from sqlalchemy import *
from base import Base

class B(Base):
    __tablename__ = "B"
    id    = Column(Integer, primary_key=True)
    A_id  = Column(Integer, ForeignKey("A.id"))

模型/c.py

​​>
from sqlalchemy import *
from base import Base

class C(Base):
    __tablename__ = "C"    
    id    = Column(Integer, primary_key=True)
    A_id  = Column(Integer, ForeignKey("A.id"))

模型/__init__.py

​​>

(空)

main.py

​​>
from sqlalchemy import create_engine
from sqlalchemy.orm import relationship, backref, sessionmaker

from model import base


from model import a
from model import b
from model import c

engine = create_engine("sqlite:///:memory:")
base.Base.metadata.create_all(engine, checkfirst=True)
Session = sessionmaker(bind=engine)
session = Session()

a1 = a.A()
b1 = b.B()
b2 = b.B()
c1 = c.C()
c2 = c.C()

a1.Bs.append(b1)
a1.Bs.append(b2)    
a1.Cs.append(c1)
a1.Cs.append(c2)    
session.add(a1)
session.commit()

python2 工作:

$ python main.py ; echo $?
0

python3 错误:

$ python3 main.py ; echo $?
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    from model import a
  File "/home/shale/code/py/try/model/a.py", line 2, in <module>
    from base import Base
ImportError: No module named base
1

我最终通过将 base.py 中的代码放入我的 __init__.py 文件中解决了这个问题(如下面的一个答案),但有谁知道为什么这会在 python3 中产生错误,但在 python2 中却没有?首先是什么变化造成的?

【问题讨论】:

    标签: python python-3.x sqlalchemy


    【解决方案1】:

    Python 3 默认切换到 absolute 导入,并且不允许不合格的相对导入。 from base import Base 行就是这样一个导入。

    Python 3 只会寻找顶级模块;你没有base 顶级模块,只有model.base。使用完整的模块路径,或使用相对限定符:

    from .base import Base
    

    开头的. 告诉 Python 3 从当前包开始导入。

    您可以通过添加以下内容在 Python 2 中启用相同的行为:

    from __future__ import absolute_import
    

    这是PEP 328 引入的更改,from future 导入从 Python 2.5 开始可用。

    【讨论】:

    • 美丽。这在 python2 和 python3 中有效,并清楚地解释了错误出现在 python3 之前的位置。谢谢! (对于一个简单的答案,很抱歉提出这么长的问题。)
    【解决方案2】:

    我找到的一个解决方案是:

    • 将代码从 base.py 移动到 __init__.py。
    • 将 a.py、b.py 和 c.py 中的 import base 行更改为 from . import Base
    • 在model.py中将from model import base改为from model import Base
    • 也在 model.py 中将 base.Base 更改为 Base

    我仍然不确定为什么以前的设计适用于 python2 而不是 python3。上面的改动使它在 python2 和 python3 中都可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-04
      • 2019-06-06
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 2015-05-24
      相关资源
      最近更新 更多