简体   繁体   English

如何在pyqt中设置QThread的名称?

[英]How to set the name of a QThread in pyqt?

I am using QtCore.QThread (from PyQt4 ).我正在使用QtCore.QThread (来自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调试 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....我的问题是我想更明确地知道哪个线程正在记录...... Dummy-3对我来说不是最明确的名字......

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 ?有没有办法为日志模块(作为 LogRecord 属性)使用的QtCore.QThread设置一个名称,以便使日志更有意义?

Thanks !谢谢 !

If the threading module is available, the logging module will use threading.current_thread().name to set the threadName LogRecord attribute.如果线程模块可用,日志模块将使用threading.current_thread().name设置threadName LogRecord 属性。

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).但是threading.current_thread文档说如果当前线程不是由线程模块创建的(因此是“Dummy-x”名称),则将使用一个虚拟线程对象。

I suppose it would be possible to monkey-patch threading.current_thread to reset the name to something more appropriate.我想可以通过猴子补丁threading.current_thread将名称重置为更合适的名称。 But surely a much better approach would be to make use of the extra dictionary when logging a message:但肯定更好的方法是在记录消息时使用extra字典:

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 nameQt5 文档中,您可以调用setObjectName()来修改线程名称

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.要选择线程的名称(例如,在 Linux 上由命令 ps -L 标识),您可以在启动线程之前调用 setObjectName()。

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).如果您不调用 setObjectName(),则为线程指定的名称将是线程对象的运行时类型的类名(例如,在 Mandelbrot 示例中为“RenderThread”,因为这是QThread 子类)。

Unfortunately, it also notes:不幸的是,它还指出:

this is currently not available with release builds on Windows.这目前不适用于 Windows 上的发布版本。

I had exactly your problem: I have a Qt GUI app running in the main thread and several Workers running in separate threads.我确实遇到了您的问题:我在主线程中运行了一个 Qt GUI 应用程序,并且在单独的线程中运行了几个 Worker。

I started using the extras = {'qthreadname': get_qthreadname()} approach suggested by Ekhumoro, but the problem was the integration with other libraries using logging.我开始使用 Ekhumoro 建议的extras = {'qthreadname': get_qthreadname()}方法,但问题是使用日志记录与其他库集成。 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.例如,在上面的示例中,Formatter 已经设置了一个格式字符串,该字符串在 LogRecord 的属性字典中需要“clientip”和“user”。 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).虽然这可能很烦人,但此功能旨在用于特殊情况,例如在许多上下文中执行相同代码的多线程服务器,并且出现的有趣条件取决于此上下文(例如远程客户端 IP 地址和经过身份验证的用户名,在上面的示例中)。 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. QThread 也是一个线程,您始终可以获取对当前线程的引用并设置其名称。 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.现在所有来自 QThread 的日志消息都被正确识别了。

I hope it can help you!我希望它可以帮助你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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