2016-11-15 57 views
1

我正在尋找一種使用Python轉儲PostgreSQL數據庫模式的方法。理想情況下,結果將是.sql轉儲或任何其他格式,稍後可由SQLAlchemy使用該格式從該模式創建新數據庫。使用Python轉儲PostgreSQL數據庫模式

我做了這個實驗的SQLAlchemy的MetaData class

from sqlalchemy import MetaData, create_engine 

engine = create_engine(source_database_url) 
test_engine = create_engine(test_database_url) 
metadata = MetaData() 
metadata.reflect(engine) 
metadata.create_all(test_engine) 

這正是我想要做,除了出口的模式供以後使用的東西。所以,考慮到SQLAlchemy可以成功地反映一個模式並基於它創建另一個表,我希望有一種方法可以在程序中以編程方式導出它。

我知道我可以從代碼中調用pg_dumppg_restore,但我想避免外部依賴以及隨之而來的麻煩。

有沒有辦法用SQLAlchemy或其他Python庫實現這一點?

回答

2

經過深入挖掘,我發現這個helpful section from SQLAlchemy docs。 那麼,從這個代碼片段開始,我創建了下面的類:

import io 
from sqlalchemy import create_engine, MetaData 
from sqlalchemy.orm import sessionmaker 

class SchemaDump(object): 
    def __init__(self, db_url, schema_file_path): 
     self.db_url = db_url 
     self.schema_file_path = schema_file_path 
     self.buf = io.BytesIO() 

    def dump_shema(self): 
     engine = create_engine(self.db_url) 
     metadata = MetaData() 
     metadata.reflect(engine) 

     def dump(sql, *multiparams, **params): 
      f = sql.compile(dialect=engine.dialect) 
      self.buf.write(str(f)) 
      self.buf.write(str(';\n')) 

     new_engine = create_engine(self.db_url, strategy='mock', executor=dump) 
     metadata.create_all(new_engine, checkfirst=True) 

     with io.open(self.schema_file_path, 'wb+') as schema: 
      schema.write(self.buf.getvalue()) 

這仍然是相當模糊,但其主要思想是,以捕捉sql.compile(dialect=engine.dialect)返回的原始SQL語句buf,並將它們寫入文件。

我寫了一個同樣粗略類從通過上述類創建的.sql轉儲恢復數據庫:

import io 
from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 

class RestoreSchema(object): 
    def __init__(self, db_url, schema_file_path): 
     self.db_url = db_url 
     self.schema_file_path = schema_file_path 

    def restore_schema(self): 
     raw_schema = '' 
     with io.open(self.schema_file_path) as sql_schema: 
      raw_schema = sql_schema.read() 
     engine = create_engine(self.db_url) 
     Session = sessionmaker(bind=engine) 
     session = Session() 
     conn = engine.connect() 
     transaction = conn.begin() 
     try: 
      conn.execute(raw_schema) 
      transaction.commit() 
     except Exception as e: 
      transaction.rollback() 
      raise e 
     finally: 
      session.close() 

你還是擔心的表是否已經存在等,但效果是完全與我的問題中的代碼片段相同。

相關問題