集中型の sqlite データベースを使用してさまざまなファイルに関する情報を格納する Python + SQLAlchemy アプリケーションを作成しようとしています。チェックサムを使用して、各ファイルおよび/またはファイル バージョンがデータベースに 1 回だけ保存されることを確認するためUniqueConstraint
、チェックサム列に .
DbFile
さらに操作を行いたいオブジェクトにファイル情報を保存しています。オブジェクトNew()
を返す静的メソッドを作成しました。DbFile
ファイルがデータベースに既に存在する場合、そのオブジェクトが返されます。それ以外の場合は、新しいオブジェクトが作成されます。
import md5
# Not shown: sqlalchemy imports
Base = declarative_base()
engine = create_engine('sqlite:///test.db')
Session = sessionmaker(bind=engine)
session = Session()
class DbFile(Base):
id = Column(Integer, primary_key=True)
filename = Column(String, nullable=False)
checksum = Column(String, nullable=False)
__table_args__ = (UniqueConstraint('checksum'),)
@staticmethod
def New(filename):
file_md5 = md5.md5(open(filename).read())
checksum = file_md5.hexdigest()
q = session.query(Files).filter(Files.checksum == checksum)
if q.count() == 1:
print "Loading existing file object from database"
return q.one()
dbfile = DbFile(filename=filename, checksum=checksum)
いくつかのファイルをロードした後、session.commit()
. これは、データベースにアクセスしているプロセスが 1 つだけの場合は正常に機能しますが、複数の python プロセスを (コマンド ラインから) 開始すると、そのうちの 1 つがsqlalchemy.exc.IntegrityError
チェックサムの一意のキー制約に違反していると不平を言って常に中止されます。存在の確認とデータベースへの書き込みの間に競合状態が発生していることは明らかですが、それを防ぐ良い方法は見つかりませんでした。
エラーをトラップしようとしましたが、ステートメントsession.commit()
によってエラーが発生することがあります。q.count()
これを行うためのきれいな方法はありますか?