3 votos

El plugin bloquea QGIS 2.18 si se ejecuta simultáneamente con la consola de Python

Actualmente estoy desarrollando un plugin para QGIS 2.18. Desde el principio estoy teniendo el mismo problema. QGIS 2.18 se bloquea si ejecuto la consola de python mientras el plugin está trabajando algo.

Vi que las declaraciones de impresión podrían ser la causa, así que las redirigí al archivo de registro. Es interesante porque el plugin funciona perfectamente mientras que la consola de python no funciona y realmente no tengo ni idea.

Esto es lo que obtengo después del choque:

Fatal: Assertion [useCount == 0] failed at ../src/PositionCache.cpp 263

Stacktrace (piped through c++filt):

/usr/bin/qgis.bin(+0xaffa)[0x555dc646affa]
/usr/bin/qgis.bin(+0xb235)[0x555dc646b235]
/usr/lib/x86_64-linux-gnu/libQtCore.so.4(qt_message_output(QtMsgType, char const*)+0x2f)[0x7f64cdc90e9f]
/usr/lib/x86_64-linux-gnu/libQtCore.so.4(+0x70371)[0x7f64cdc91371]
/usr/lib/x86_64-linux-gnu/libQtCore.so.4(qFatal(char const*, ...)+0xa1)[0x7f64cdc91c91]
/usr/lib/libqscintilla2.so.12(Platform::Assert(char const*, char const*, int)+0x32)[0x7f64c83a632c]
/usr/lib/libqscintilla2.so.12(LineLayoutCache::AllocateForLevel(int, int)+0x35)[0x7f64c84cbafb]
/usr/lib/libqscintilla2.so.12(LineLayoutCache::Retrieve(int, int, int, int, int, int)+0x34)[0x7f64c84cbe46]
/usr/lib/libqscintilla2.so.12(EditView::RetrieveLineLayout(int, EditModel const&)+0x143)[0x7f64c84b286d]
/usr/lib/libqscintilla2.so.12(Editor::SetAnnotationHeights(int, int)+0xd1)[0x7f64c84a2605]
/usr/lib/libqscintilla2.so.12(Editor::CheckModificationForWrap(DocModification)+0xc4)[0x7f64c849622c]
/usr/lib/libqscintilla2.so.12(Editor::NotifyModified(Document*, DocModification, void*)+0x790)[0x7f64c8496a1e]
/usr/lib/libqscintilla2.so.12(Document::NotifyModified(DocModification)+0xf5)[0x7f64c8486391]
/usr/lib/libqscintilla2.so.12(Document::InsertString(int, char const*, int)+0x309)[0x7f64c8481d9f]
/usr/lib/libqscintilla2.so.12(Editor::WndProc(unsigned int, unsigned long, long)+0x17a1)[0x7f64c84a6111]
/usr/lib/libqscintilla2.so.12(ScintillaBase::WndProc(unsigned int, unsigned long, long)+0xf16)[0x7f64c84d8a90]
/usr/lib/libqscintilla2.so.12(QsciScintillaQt::WndProc(unsigned int, unsigned long, long)+0x53)[0x7f64c83a79a1]
/usr/lib/libqscintilla2.so.12(QsciScintillaBase::SendScintilla(unsigned int, unsigned long, char const*) const+0x3e)[0x7f64c836d5fe]
/usr/lib/libqscintilla2.so.12(QsciScintilla::append(QString const&)+0x78)[0x7f64c836543c]
/usr/lib/python2.7/dist-packages/PyQt4/Qsci.x86_64-linux-gnu.so(+0xdc209)[0x7f641ca5e209]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_EvalFrameEx+0x8a51)[0x7f64203d6751]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_EvalCodeEx+0x85c)[0x7f64204ff01c]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(+0x13e2e0)[0x7f64204552e0]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyObject_Call+0x43)[0x7f64204281e3]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(+0x18531c)[0x7f642049c31c]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyObject_Call+0x43)[0x7f64204281e3]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_CallObjectWithKeywords+0x47)[0x7f64204fe447]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyFile_WriteObject+0x152)[0x7f642046b4d2]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_EvalFrameEx+0x582c)[0x7f64203d352c]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_EvalFrameEx+0x7124)[0x7f64203d4e24]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_EvalCodeEx+0x85c)[0x7f64204ff01c]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(+0x13e2e0)[0x7f64204552e0]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyObject_Call+0x43)[0x7f64204281e3]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(+0x18531c)[0x7f642049c31c]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyObject_Call+0x43)[0x7f64204281e3]
/usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0(PyEval_CallObjectWithKeywords+0x47)[0x7f64204fe447]
/usr/lib/python2.7/dist-packages/sip.x86_64-linux-gnu.so(+0xfe44)[0x7f6420004e44]
/usr/lib/python2.7/dist-packages/PyQt4/QtCore.so(+0x8be60)[0x7f641fbe2e60]
/usr/lib/python2.7/dist-packages/PyQt4/QtCore.so(+0xdc59e)[0x7f641fc3359e]
/usr/lib/x86_64-linux-gnu/libQtCore.so.4(+0x7ae3c)[0x7f64cdc9be3c]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x76ba)[0x7f64c5e5e6ba]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f64cc6d23dd]

El comportamiento es el mismo en Windows

8voto

Michael Puntos 11

Esto es efectivamente un efecto de usar la sentencia print y tener la consola de python abierta. Y utilizando la sentencia logging El módulo propuesto es un muy buen enfoque para resolver este problema.

A continuación, algunas reflexiones sobre lo que ocurre exactamente. Todo se reduce a print() llamando internamente QCoreApplication::processEvents() y processEvents() es malo y peligroso .

La consola de python siempre llamará a QCoreAppliation::processEvents() cuando se imprime algo. La razón de esto es, que los eventos de pintura de la consola necesitan ser procesados para que el texto impreso aparezca en la consola.

Los eventos se procesan siempre que QGIS tiene tiempo normalmente. Pero en la consola de python a veces se realizan bucles de larga duración que mantienen a QGIS ocupado, por lo que no trabajará en los eventos pendientes hasta que el bucle termine.

Sin embargo, processEvents() no sólo funcionará en las actualizaciones de la pantalla, sino que también se encargará de la entrada del usuario y de las conexiones de las señales/ranuras. Esto a veces ejecutará código de forma recursiva que no fue diseñado para ser ejecutado de forma recursiva o de otra forma ejecutará código en un contexto diferente al esperado .

  1. Utilice un módulo como logging o QgsMessageLog en lugar de utilizar print para la depuración
  2. Especialmente no utilice print() en ranuras conectadas a ranuras conectadas a señales activadas por la entrada del usuario (como los eventos de navegación del lienzo del mapa)
  3. No utilice processEvents() en su propio código. Si utiliza QGIS 3, considere la posibilidad de implementar una QgsTask para el código de larga duración.

Situación en QGIS 3

En QGIS 3 print() ya no desencadena un processEvents() y, por lo tanto, su uso es seguro. Sin embargo, llamar a processEvents() de su propio código sigue siendo peligroso.

4voto

J. Peterson Puntos 720

Solucionado, parece que he abusado de la sentencia print mientras depuraba en python. Cambiando al módulo logging se solucionó el problema. Utiliza el módulo logging en lugar de print, es mucho más cómodo y práctico. Es una molestia al principio, pero una vez que lo consigues es bastante fácil. Aquí hay algunos enlaces que fueron muy útiles para mí:

http://docs.python-guide.org/en/latest/writing/logging/

https://fangpenlin.com/posts/2012/08/26/good-logging-practice-in-python/

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X