9

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 ファイルに入れることでこれを解決しました (以下の 1 つの回答として説明)。そもそもこれの原因はどのような変化ですか?

4

2 に答える 2

9

Python 3はデフォルトで絶対インポートに切り替え、非修飾の相対インポートを許可しません。ラインは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 以降で利用できます。

于 2013-10-28T20:57:33.467 に答える
0

私が見つけた1つの解決策は次のとおりです。

  • コードを base.py から __init__.py に移動します。
  • import basea.py、b.py、および c.pyの行を次のように変更します。from . import Base
  • model.pyfrom model import basefrom model import Base
  • また、model.py に変更base.BaseBaseます。

以前の設計が python2 では機能するのに python3 では機能しない理由はまだわかりません。上記の変更により、python2 と python3 の両方で機能します。

于 2013-10-28T20:54:13.667 に答える