简体   繁体   中英

How to set the name of a QThread in pyqt?

I am using QtCore.QThread (from PyQt4 ).

To log, I am also using the following formatter :

logging.Formatter('%(levelname)-8s %(asctime)s %(threadName)-15s %(message)s')

The resulting log is :

DEBUG 2012-10-01 03:59:31,479 Dummy-3 my_message

My problem is that I want to know more explicitly which thread is logging... Dummy-3 is not the most explicit name to me....

Is there a way to set a name to a QtCore.QThread that will be usable by the logging module (as a LogRecord attribute) in order to have a log more meaningful ?

Thanks !

If the threading module is available, the logging module will use threading.current_thread().name to set the threadName LogRecord attribute.

But the docs for threading.current_thread say that a dummy thread object will be used if the current thread was not created by the threading module (hence the "Dummy-x" name).

I suppose it would be possible to monkey-patch threading.current_thread to reset the name to something more appropriate. But surely a much better approach would be to make use of the extra dictionary when logging a message:

logging.Formatter('%(levelname)-8s %(asctime)s %(qthreadname)-15s %(message)s')
...
extras = {'qthreadname': get_qthreadname()}
logging.warning(message, extra=extras)

From the Qt5 documentation , you can call setObjectName() to modify the thread name

To choose the name that your thread will be given (as identified by the command ps -L on Linux, for example), you can call setObjectName() before starting the thread.

If you don't call setObjectName(), the name given to your thread will be the class name of the runtime type of your thread object (for example, "RenderThread" in the case of the Mandelbrot Example, as that is the name of the QThread subclass).

Unfortunately, it also notes:

this is currently not available with release builds on Windows.

I had exactly your problem: I have a Qt GUI app running in the main thread and several Workers running in separate threads.

I started using the extras = {'qthreadname': get_qthreadname()} approach suggested by Ekhumoro, but the problem was the integration with other libraries using logging. If you don't provide the extra dictionary, logging will throw an exception as written in the doc and here summarized:

If you choose to use these attributes in logged messages, you need to exercise some care. In the above example, for instance, the Formatter has been set up with a format string which expects 'clientip' and 'user' in the attribute dictionary of the LogRecord. If these are missing, the message will not be logged because a string formatting exception will occur. So in this case, you always need to pass the extra dictionary with these keys. While this might be annoying, this feature is intended for use in specialized circumstances, such as multi-threaded servers where the same code executes in many contexts, and interesting conditions which arise are dependent on this context (such as remote client IP address and authenticated user name, in the above example). In such circumstances, it is likely that specialized Formatters would be used with particular Handlers.

Instead of having specialized Formatters and Handlers, I have found a different approach. A QThread is also a thread and you can always get a reference to the current thread and set its name. Here a snippet of my code:

import threading
# 
# your code
worker = MyWorker()
worker_thread = QThread()
worker_thread.setObjectName('MyThread')
worker.moveToThread(worker_thread)
#
# your code


class MyWorker(QtCore.QtObject):
   # your code

   def start(self):
       threading.current_thread().name = QtCore.QThread.currentThread().objectName() 
       # your code

Now all the log messages arriving from the QThread are properly identify.

I hope it can help you!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM