我用這種邏輯編寫了一個腳本,以便在生成PostgreSQL表時將許多記錄插入到PostgreSQL表中。SQLAlchemy ThreadPoolExecutor「客戶端太多」
#!/usr/bin/env python3
import asyncio
from concurrent.futures import ProcessPoolExecutor as pool
from functools import partial
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
metadata = sa.MetaData(schema='stackoverflow')
Base = declarative_base(metadata=metadata)
class Example(Base):
__tablename__ = 'example'
pk = sa.Column(sa.Integer, primary_key=True)
text = sa.Column(sa.Text)
sa.event.listen(Base.metadata, 'before_create',
sa.DDL('CREATE SCHEMA IF NOT EXISTS stackoverflow'))
engine = sa.create_engine(
'postgresql+psycopg2://postgres:[email protected]:5432/stackoverflow'
)
Base.metadata.create_all(engine)
session = sa.orm.sessionmaker(bind=engine, autocommit=True)()
def task(value):
engine.dispose()
with session.begin():
session.add(Example(text=value))
async def infinite_task(loop):
spawn_task = partial(loop.run_in_executor, None, task)
while True:
await asyncio.wait([spawn_task(value) for value in range(10000)])
def main():
loop = asyncio.get_event_loop()
with pool() as executor:
loop.set_default_executor(executor)
asyncio.ensure_future(infinite_task(loop))
loop.run_forever()
loop.close()
if __name__ == '__main__':
main()
此代碼工作得很好,創造儘可能多的進程池,因爲我有個CPU核心,並愉快地沿着隆隆永遠。我想看看線程如何與進程進行比較,但我無法得到一個有效的示例。下面是我所做的更改:
from concurrent.futures import ThreadPoolExecutor as pool
session_maker = sa.orm.sessionmaker(bind=engine, autocommit=True)
Session = sa.orm.scoped_session(session_maker)
def task(value):
engine.dispose()
# create new session per thread
session = Session()
with session.begin():
session.add(Example(text=value))
# remove session once the work is done
Session.remove()
了一段時間的「太多的客戶」異常洪水之前,此版本的運行:
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL: sorry, too many clients already
我缺少什麼?
@txomon:它是'Session.remove()',而不是'session.remove()'(嘗試編輯但被拒絕)。原因在於''sessionmaker'工廠實例具有'remove()'方法(您正在調用工廠將當前會話從池中取消引用;會話不會自行移除)。請參閱:http://docs.sqlalchemy.org/en/latest/orm/contextual.html – cowbert