0

Python で sqlite データベースへの sqlalchemy マッピングを設定するときに、「相互に依存するコードの配置」に関して少し問題があります。

目標は、次の条件を満たすスクリプトを作成することです。

  1. filenameコマンド ライン引数としてパラメーターを取得します。
  2. に基づいてfilename、SQLite データベースへの絶対パスを作成する必要があります。
  3. データベースに接続し、engine
  4. このデータベースのテーブルを反映する必要があります。
  5. テーブルには主キーがなく、sqlalchemy が主キーを必要とするため、テーブル内の列を主キー列にする必要がありますmonkey patchidmytable

だから私はこれを思いついた:

from sqlalchemy import create_engine, Column, Integer
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base  

def create_path(file_name):
    # generate absolute path to file_name

path_to_file = create_path("my_file_name.sqlite")
engine = create_engine('sqlite:///{path}'.format(path=path_to_file), echo=False)
Base = declarative_base()
Base.metadata.create_all(engine)

class MyTable(Base):
    __tablename__ = 'my_table'
    __table_args__ = {'autoload': True}

    id = Column(Integer, primary_key=True) # Monkey patching the id column as primary key.

def main(argv):
    # parse file_name here from argv
    Session = sessionmaker(bind=engine)
    session = Session()
    for row in session.query(MyTable).all():
        print row
    return "Stop!"

if __name__ == '__main__':
    sys.exit(main())

しかし、これは運命の構造であり、依存関係を壊さずにコードを再配置する方法がわかりません。

  1. Iを作成できるようにするには、 の前に I を定義するMyClass必要があります。BaseMyClass
  2. Iを作成できるようにするには、 の前に I を定義するBase必要があります。engineBase
  3. Iを作成できるようにするには、 の前に I を定義するengine必要があります。path_to_fileengine
  4. path_to_fileIの外部で作成できるようにするには、 の前に定義するmain()必要があります。create_file()path_to_file
  5. 等々...

うまくいけば、私が立ち往生している場所がわかります...

助言がありますか?

編集:ちなみに、コードは機能しますが、スクリプトの先頭にハードコードされたファイル名のみがあります。

4

3 に答える 3

1

SQLAlchemy の古典的なマッピング アプローチを使用して問題を解決しました。

from sqlalchemy import create_engine, Column, Integer, MetaData, Table
from sqlalchemy.orm import sessionmaker, mapper

class MyTable(object):    
    pass    

def main():
    path_to_file = create_path("my_file_name.sqlite")
    engine = create_engine('sqlite:///{path}'.format(path=path_to_file), echo=False)

    metadata = MetaData()
    metadata.bind = engine
    my_table = Table('mytable',
                     metadata,
                     Column('id', Integer, primary_key=True), # Monkey patching the id column as primary key.
                     autoload=True,
                     autoload_with=engine)
    mapper(MyTable, my_table)

    Session = sessionmaker(bind=engine)
    session = Session()

    # Do Stuff!
于 2012-04-07T08:08:25.203 に答える
1

declarativeマッピングをまだ完全に使用できなかった理由がわかりません。適切な依存関係の鍵は、モジュールに何を入れ、スクリプト/関数に何を入れるかを知ることだと思います。Python では、関数内でクラスを簡単に定義できますrun_script

from sqlalchemy import create_engine, Column, Integer
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

def create_path(filename):
    import os
    fn = os.path.abspath(os.path.join(os.path.dirname(__file__), 'sqlite_files', filename))
    return fn

def run_script(filename):
    path_to_file = create_path(filename)

    engine = create_engine('sqlite:///{path}'.format(path=path_to_file), echo=True)
    Session = sessionmaker(bind=engine)
    Base = declarative_base(bind=engine)

    # object model
    class MyTable(Base):
        __tablename__ = 'my_table'
        __table_args__ = {'autoload': True}
        id = Column(Integer, primary_key=True) # Monkey patching the id column as primary key

    # script itself
    session = Session()
    for row in session.query(MyTable).all():
        print row
    return "Stop!"

def main(argv):
    assert argv, "must specify a database file name"
    run_script(argv[0])

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
于 2012-04-12T16:00:27.653 に答える
0

現在の場所でテストを行う能力がありません。しかし、そのコードをすべて次のように移動することをお勧めしmain()ます。また、MyTableサブクラスdeclarative_base.

from sqlalchemy import create_engine, Column, Integer 
from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base    

class MyTable(declarative_base):     
    __tablename__ = 'my_table'     
    __table_args__ = {'autoload': True}      

    id = Column(Integer, primary_key=True) # Monkey patching the id column as primary key.  

def create_path(file_name):     
    # generate absolute path to file_name  


def main(argv):     # parse file_name here from argv   
    path_to_file = create_path("my_file_name.sqlite") 
    engine = create_engine('sqlite:///{path}'.format(path=path_to_file), echo=False) 
    Base = MyTable()
    Base.metadata.create_all(engine)  

    Session = sessionmaker(bind=engine)     
    session = Session()     
    for row in session.query(MyTable).all():         
        print row     
    return "Stop!"  

if __name__ == '__main__':     
    sys.exit(main()) 
于 2012-04-05T20:53:24.163 に答える