this is all about whatever you've done specifically. If you have the Session instance still around, where my_session.bind still points to your Engine, then that Engine is still in memory - you're holding a reference to it. Similarly, if you've assigned an event to the Session class whose callable refers to the Engine in question, then the Engine is still referenced as well, such as:
def make_evt(engine):
@event.listens_for(Session, "before_flush")
def go(session, ctx):
# do something with engine
make_evt(my_engine)
the above code will associate "my_engine" with a class-level Session listener and cannot be dereferenced without unloading all of sqlalchemy.orm.
dispose() and NullPool have *nothing to do* with the Engine itself, only the connections inside the pool contained within. Your Engine will remain present as long as its reachable via references, just like any other Python object.