如何在obj上要求python的“with”语句

2024-10-02 12:26:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用python的SQLAlchemy工具包编写一个数据库访问层。我一直在研究使层线程安全和资源可靠的最佳方法。为了实现这一点,我偶然发现了在创建db引擎时可以传递的NullPool对象。在

为了让DAOs“负责资源”,我考虑过在try/catch/finally块结束时关闭会话,但是我不想采用这种方式,因为我希望只要使用者需要DAO来进行数据库操作,连接就保持打开状态。作为在对象生命周期结束时关闭连接的方法,我想使用with语句__enter__和{}方法。enter方法将返回对象的实例,exit方法将在对象使用结束时执行session.close()。在

但是,我想做的是要求用python with语句实例化对象,这样,如果对象是以任何其他方式创建的,则实例化将失败。在

有没有办法做到这一点?我已将类和用法声明包括在下面:

class RegionDAO(declarative_base()):                                             

     __tablename__ = 'region'                                                     

     region_id = Column(Integer, primary_key=True)                                
     country_id = Column(Integer, primary_key=True)                               
     description = Column(String, nullable=False)                                 
     code = Column(String, nullable=False)                                        
     region_type = Column(Integer)                                                
     sort_order = Column(Integer)                                                 

     def __init__(self):                                                          
         connection, meta = PG.get_connection()                                   
         Session = sessionmaker(bind=connection)                                  
         self.session = Session()                           

     def __enter__(self):                                                         
         return self                                                              

     def select_all(self):                                                        
         for row in self.session.query(RegionDAO).all():                          
             print("[" + row.description + "] - [" + row.code + "]")              

     def __exit__(self, exc_type, exc_value, traceback):                          
         print("Exit being called, cleaning up session")                          
         self.session.close()                                                     

 #                                                                                
 # main                                                                           
 #                                                                                

 if __name__ == "__main__":

     # This should succeed                                                       
     with RegionDAO() as r:                                                      
         r.select_all()                                                          

     # This should fail                                                                                  
     r = RegionDAO()                                                              
     r.select_all()  

编辑-在阅读了一些评论之后,我想我可能造成了一些混乱。我的最终目标是——当对象完成使用后,连接就关闭了。(在本例中,连接是由于使用了NullPool对象而成为会话)


Tags: 对象实例方法selfsessiondefwithcolumn
1条回答
网友
1楼 · 发布于 2024-10-02 12:26:10

我不是建议你这样做,因为这与OOP中的典型假设相反,但是如果你真的需要来完成这一点,你可以确保你不能用调用外部实例化的对象的方法,但是根本没有办法禁止实例的创建。在

由于上下文管理器为构造函数提供了任何东西,而只是调用enterexit我唯一能看到的方法就是确保类提供的所有方法都是先检查是否调用了enter,而且,我将把所有的逻辑移到enter而不是constructor(因为如果您想禁止任何其他用法,那么在init中执行任何总是后跟enter的操作有什么意义?)在

 def __init__(self):                                                          
     self.session = None                       

 def __enter__(self): 
     connection, meta = PG.get_connection()                                   
     Session = sessionmaker(bind=connection)                                  
     self.session = Session()    
     return self                                                              

 def select_all(self):
     if self.session is None:
       raise Exception('This class can only be used as a context manager')                                                        
     for row in self.session.query(RegionDAO).all():                          
         print("[" + row.description + "] - [" + row.code + "]")  

或者,如果您想保留以前的方法,只需在enter

^{pr2}$

相关问题 更多 >

    热门问题