2015-09-25 2 views
0

J'utilise python 3.4 et sqlalchemy et pymsql et gevent et céleri ensemble dans mon application. Parfois, lors d'un appel de base de données SQL, l'erreur suivante se produira, aucune idée de la raison pour laquelle cela se produirait. Des idées?Python3 sqlalchemy pymysql gevent sqlalchemy.util.queue.Empty gevent.hub.LoopExit: Cette opération bloquerait pour toujours

[2015-09-24 15:19:32,790: ERROR/Worker-1] Exception during reset or similar 
Traceback (most recent call last): 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 950, in _do_get 
    return self._pool.get(wait, self._timeout) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/queue.py", line 145, in get 
    raise Empty 
sqlalchemy.util.queue.Empty 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 567, in _finalize_fairy 
    fairy._reset(pool) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 701, in _reset 
    pool._dialect.do_rollback(self) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/dialects/mysql/base.py", line 2354, in do_rollback 
    dbapi_connection.rollback() 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/connections.py", line 711, in rollback 
    self._read_ok_packet() 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/connections.py", line 685, in _read_ok_packet 
    pkt = self._read_packet() 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/connections.py", line 882, in _read_packet 
    packet_header = self._read_bytes(4) 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/connections.py", line 899, in _read_bytes 
    data = self._rfile.read(num_bytes) 
  File "/usr/lib/python3.4/socket.py", line 371, in readinto 
    return self._sock.recv_into(b) 
  File "/usr/local/lib/python3.4/dist-packages/gevent/_socket3.py", line 282, in recv_into 
    self._wait(self._read_event) 
  File "/usr/local/lib/python3.4/dist-packages/gevent/_socket3.py", line 97, in _wait 
    self.hub.wait(watcher) 
  File "/usr/local/lib/python3.4/dist-packages/gevent/hub.py", line 360, in wait 
    assert result is unique, 'Invalid switch into %s: %r (expected %r)' % (getcurrent(), result, unique) 
AssertionError: Invalid switch into <greenlet.greenlet object at 0x7fb774422800>: <gevent.event.AsyncResult object at 0x7fb76d323198> (expected <object object at 0x7fb777ff82d0>) 
[2015-09-24 15:19:32,911: ERROR/MainProcess] Task ppp.start_job[b574f2cd-4e9d-4f0f-97cc-79dd1ddee666] raised unexpected: LoopExit('This operation would block forever',) 
Traceback (most recent call last): 
  File "/usr/local/lib/python3.4/dist-packages/celery/app/trace.py", line 240, in trace_task 
    R = retval = fun(*args, **kwargs) 
  File "/usr/local/lib/python3.4/dist-packages/celery/app/trace.py", line 438, in __protected_call__ 
    return self.run(*args, **kwargs) 
  File "/home/aaa/ppp/tasks/start_job.py", line 45, in start_job 
    add_all_to_db(data_to_insert) 
  File "/home/aaa/ppp/tasks/utils/sqldb.py", line 284, in add_all_to_db 
    session.close() 
  File "/home/aaa/ppp/tasks/utils/sqldb.py", line 270, in get_session 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/schema.py", line 3404, in create_all 
    tables=tables) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1615, in _run_visitor 
    with self._optional_conn_ctx_manager(connection) as conn: 
  File "/usr/lib/python3.4/contextlib.py", line 59, in __enter__ 
    return next(self.gen) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1608, in _optional_conn_ctx_manager 
    with self.contextual_connect() as conn: 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1798, in contextual_connect 
    self.pool.connect(), 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 338, in connect 
    return _ConnectionFairy._checkout(self) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 644, in _checkout 
    fairy = _ConnectionRecord.checkout(pool) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 440, in checkout 
    rec = pool._do_get() 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 963, in _do_get 
    return self._create_connection() 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 285, in _create_connection 
    return _ConnectionRecord(self) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 411, in __init__ 
    self.connection = self.__connect() 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/pool.py", line 538, in __connect 
    connection = self.__pool._creator() 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/strategies.py", line 90, in connect 
    return dialect.connect(*cargs, **cparams) 
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/default.py", line 377, in connect 
    return self.dbapi.connect(*cargs, **cparams) 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/__init__.py", line 88, in Connect 
    return Connection(*args, **kwargs) 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/connections.py", line 644, in __init__ 
    self._connect() 
  File "/usr/local/lib/python3.4/dist-packages/pymysql/connections.py", line 823, in _connect 
    (self.host, self.port), self.connect_timeout) 
  File "/usr/local/lib/python3.4/dist-packages/gevent/socket.py", line 51, in create_connection 
    for res in getaddrinfo(host, port, 0 if has_ipv6 else AF_INET, SOCK_STREAM): 
  File "/usr/local/lib/python3.4/dist-packages/gevent/_socketcommon.py", line 193, in getaddrinfo 
    return get_hub().resolver.getaddrinfo(host, port, family, socktype, proto, flags) 
  File "/usr/local/lib/python3.4/dist-packages/gevent/resolver_thread.py", line 34, in getaddrinfo 
    return self.pool.apply_e(self.expected_errors, _socket.getaddrinfo, args, kwargs) 
  File "/usr/local/lib/python3.4/dist-packages/gevent/threadpool.py", line 222, in apply_e 
    success, result = self.spawn(wrap_errors, expected_errors, function, args, kwargs).get() 
  File "/usr/local/lib/python3.4/dist-packages/gevent/event.py", line 233, in get 
    result = self.hub.switch() 
  File "/usr/local/lib/python3.4/dist-packages/gevent/hub.py", line 349, in switch 
    return greenlet.switch(self) 
gevent.hub.LoopExit: This operation would block forever 

Ma fonction get_session:

def get_session(): 
    engine = create_engine('mysql+pymysql://{0}:{1}@{2}/{3}'.format(SQL_USR, SQL_PASS, SQL_HOST, DB_NAME), 
          echo=True, pool_size=200, pool_recycle=360) 
    Base.metadata.create_all(engine) 
    Session = sessionmaker(bind=engine) 
    session = Session() 
    return session 

Répondre

0

Cette semaine, j'ai connu quelques problèmes étranges un peu semblable à la vôtre, avec python3.4, sqlalchemy et oracle. Je poste la solution que j'ai trouvée au cas où cela vous aiderait.

J'ai quelques programmes qui fonctionnent parfaitement bien pour python2.7, mais de temps en temps j'ai passé du temps à essayer de les mettre en 3.4. Vous avez plusieurs échecs, certains d'entre eux liés à oracle par sqlalchemy et suivant une sorte de modèle. Le scénario le plus simple dans lequel il échouait était lors du chargement des données dans la base de données; Fondamentalement, le programme serait bloqué pour toujours. Je n'ai pas obtenu une exception comme la vôtre, mais je suppose que l'origine du problème pourrait être similaire à la vôtre.

J'ai pensé à poster une question ici, mais je m'attendais à ce que ce soit juste un problème d'installation dans ma machine, et de toute façon je ne saurais pas comment exprimer la question d'une manière significative. Je l'ai fait pas mal d'essais et a obtenu que le scénario simple fonctionnait bien pour

  • postgresql pour les 2.7 et 3.4
  • oracle pour 2.7 que je mentionne ci-dessus

Cela me conduit dans d'autres essais et finalement j'ai fait un changement, un peu aveuglé je dois dire, qui l'a arrangé. Je faisais la charge comme celui-ci,

for user_id in users_set: 
    reg = UserRank(user_id=int(user_id), rank_exec_id=rank_exec_id, rank_step_id=rank_step_id, 
        rank=rank_df.loc[user_id]) 
    session.add(reg) 
session.commit() 

rank_df.loc[user_id] était de type numpy.float64 et je l'ai changé pour

for user_id in users_set: 
    reg = UserRank(user_id=int(user_id), rank_exec_id=rank_exec_id, rank_step_id=rank_step_id, 
        rank=float(rank_df.loc[user_id])) 
    session.add(reg) 
session.commit() 

convertissant ainsi de python brut float. Et ça a commencé à fonctionner, même si je n'ai pas encore vraiment compris le problème.

Juste pour être complet, c'est la classe pour la table,

class UserRank(Base): 
    __tablename__ = 'user_rank' 
    user_id = Column(BigInteger, primary_key=True) 
    rank_exec_id = Column(String(256), primary_key=True) 
    rank_step_id = Column(String(256), primary_key=True) 
    rank = Column(Float) 

Honnêtement, je ne crois guère ma propre explication, mais j'espère que cela vous aide d'une certaine façon.