Why is my scoped_session raising an AttributeError: 'Session' object has no attribute 'remove'

前端 未结 1 376
醉酒成梦
醉酒成梦 2021-02-06 02:07

I\'m trying to set up a system that elegantly defers database operations to a seperate thread in order to avoid blocking during Twisted callbacks.

So far, here is my app

1条回答
  •  迷失自我
    2021-02-06 02:47

    Short answer

    Call .remove() on Session, not session.

    Long answer:

    scoped_session doesn't really return a Session class. Instead, it creates an object that pays attention to which thread it's called in. Calling it will either return the existing Session instance associated with that thread or associate a new one and return that. A thread local is what associates a thread with a session.

    The remove method on a scoped_session object removes the session object currently associated with the thread in which it's called. That means it's the opposite of scoped_session.__call__, which is kind of a confusing API.

    Here's a short Python script to illustrate the behavior.

    import threading
    from sqlalchemy import create_engine
    from sqlalchemy.orm import scoped_session, sessionmaker
    
    _engine = create_engine('sqlite:///:memory:')
    Session = scoped_session(sessionmaker(_engine))
    
    
    def scoped_session_demo(remove=False):
        ids = []
    
        def push_ids():
            thread_name = threading.currentThread().getName()
            data = [thread_name]
    
            data.append(Session())
            if remove:
                Session.remove()
            data.append(Session())
    
            ids.append(data)
    
        t = threading.Thread(target=push_ids)
        t.start()
        t.join()
    
        push_ids()
    
        sub_thread, main_thread = ids
    
        sub_name, sub_session_a, sub_session_b = sub_thread
        main_name, main_session_a, main_session_b = main_thread
    
        print sub_name, sub_session_a == sub_session_b
        print main_name, main_session_a == main_session_b
        print sub_name, '==', main_name, sub_session_a == main_session_b
    
    
    print 'Without remove:'
    scoped_session_demo()
    print 'With remove:'
    scoped_session_demo(True)
    

    Its output:

    Without remove:
    Thread-1 True
    MainThread True
    Thread-1 == MainThread False
    With remove:
    
    Thread-2 False
    MainThread False
    Thread-2 == MainThread False
    

    0 讨论(0)
提交回复
热议问题