Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python sqlalchemy自动加载orm持久性_Python_Caching_Orm_Sqlalchemy_Autoload - Fatal编程技术网

Python sqlalchemy自动加载orm持久性

Python sqlalchemy自动加载orm持久性,python,caching,orm,sqlalchemy,autoload,Python,Caching,Orm,Sqlalchemy,Autoload,我们正在使用sqlalchemy的自动加载特性进行列映射,以防止代码中出现硬编码 class users(Base): __tablename__ = 'users' __table_args__ = { 'autoload': True, 'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8' } 有没有一种方法可以序列化或缓存自动加载的元数据/orm,这样我们就不必在每次需要

我们正在使用sqlalchemy的自动加载特性进行列映射,以防止代码中出现硬编码

class users(Base):
    __tablename__ = 'users'
    __table_args__ = {
        'autoload': True,
        'mysql_engine': 'InnoDB',
        'mysql_charset': 'utf8'
    }
有没有一种方法可以序列化或缓存自动加载的元数据/orm,这样我们就不必在每次需要从其他脚本/函数引用orm类时都执行自动加载过程

我已经看过烧杯缓存和pickle,但还没有找到一个明确的答案,如果它是可能的,或者如何做到这一点

理想情况下,仅当我们已提交对数据库结构的更改,但从所有其他脚本/函数引用数据库映射的非自动加载/持久/缓存版本时,才运行autload映射脚本


有什么想法吗?

我现在要做的是在通过数据库连接(MySQL)运行反射后对元数据进行pickle,一旦pickle可用,使用该pickle元数据对绑定到SQLite引擎的元数据的模式进行反射

cachefile='orm.p'
dbfile='database'
engine_dev = create_engine(#db connect, echo=True)
engine_meta = create_engine('sqlite:///%s' % dbfile,echo=True)
Base = declarative_base()
Base.metadata.bind = engine_dev
metadata = MetaData(bind=engine_dev)

# load from pickle 
try:
    with open(cachefile, 'r') as cache:
        metadata2 = pickle.load(cache)
        metadata2.bind = engine_meta
        cache.close()
    class Users(Base):
        __table__ = Table('users', metadata2, autoload=True)

    print "ORM loaded from pickle"

# if no pickle, use reflect through database connection    
except:
    class Users(Base):
        __table__ = Table('users', metadata, autoload=True)

print "ORM through database autoload"

# create metapickle
metadata.create_all()
with open(cachefile, 'w') as cache:
    pickle.dump(metadata, cache)
    cache.close()

如果这是正确的(有效的),或者有什么我可以改进的吗?

我的解决方案与@user1572502没有太大区别,但可能有用。我将缓存的元数据文件放在
~/.sqlalchemy\u cache
中,但它们可以放在任何地方


#假设是这样的:
Base=声明性_Base(bind=引擎)
metadata\u pickle\u filename=“mydb\u metadata\u cache.pickle”
# ------------------------------------------
#加载缓存的元数据(如果可用)
# ------------------------------------------
#注意:如果数据库架构更改,请删除缓存文件!!
cache\u path=os.path.join(os.path.expanduser(“~”,.sqlalchemy\u cache”)
缓存的元数据=无
如果os.path.存在(缓存路径):
尝试:
将open(os.path.join(cache\u path,metadata\u pickle\u filename),'rb')作为cache\u文件:
cached\u metadata=pickle.load(file=cache\u file)
除IOError外:
#找不到缓存文件-没有问题
通过
# ------------------------------------------
# -----------------------------
#定义数据库表类
# -----------------------------
类MyTable(基):
如果缓存了\u元数据:
__table\uuuu=cached\u metadata.tables['my\u schema.my\u table']
其他:
__tablename\uuuu='my\u table'
__表_args_uu={'autoload':True,'schema':'my_schema'}
# ... 继续查找任何其他表。。。
# ----------------------------------------
#如果未找到缓存元数据,请保存它
# ----------------------------------------
如果缓存的_元数据为“无”:
#缓存元数据以备将来加载
#-如果数据库架构已更改,则必须删除
尝试:
如果操作系统路径不存在(缓存路径):
os.makedirs(缓存路径)
#确保以二进制模式打开-我们正在写入字节,而不是str
将open(os.path.join(cache\u path,metadata\u pickle\u filename),“wb”)作为cache\u文件:
pickle.dump(Base.metadata,缓存文件)
除:
#由于某种原因,无法写入文件
通过

重要提示如果数据库架构发生更改,则必须删除缓存文件,以强制代码自动加载并创建新缓存。如果不这样做,更改将反映在代码中。这是一件容易忘记的事情。

为什么不换一种方式:在SA中定义完整的模型。作为一个副作用,这将充当数据库模式的源代码控制。当然,这只有在SA应用程序拥有数据库的主要控制权的情况下才有效。在我的例子中,数据库开发是单独处理的,这意味着应用程序无法完全控制数据库。然而,我找到了一种方法来pickle元数据,所以我只需要通过数据库连接反射一次就可以创建pickle,我使用pickle元数据反射的时间占通过db连接反射的时间的一小部分(见下文)。您可能只需使用一个元数据对象就可以简化此过程,并且只需执行一个简单的操作“如果os.path.exists(cachefile)”,以确定是否取消勾选。“表('users',metadata,autoload=True)“这样只需要声明一次,因为您已经看到,如果表已经在元数据中,它将跳过反射。我认为在
with
语句中使用时,没有必要关闭文件,但这并不相关。你的方法似乎很有趣,是否如预期的那样有效?