Python 从线程目标访问“self”
根据许多来源,包括,将runnable作为Python 从线程目标访问“self”,python,multithreading,python-3.x,Python,Multithreading,Python 3.x,根据许多来源,包括,将runnable作为目标参数传入(带或不带args和kwargs)比扩展线程类更可取 如果我创建了一个runnable,我如何将它正在运行的线程作为self传递给它,而不扩展thread类?例如,以下方法可以很好地工作: class MyTask(Thread): def run(self): print(self.name) MyTask().start() 但是,我看不到一个好方法来让这个版本工作: def my_task(t): pr
目标
参数传入(带或不带args
和kwargs
)比扩展线程
类更可取
如果我创建了一个runnable,我如何将它正在运行的线程作为self
传递给它,而不扩展thread
类?例如,以下方法可以很好地工作:
class MyTask(Thread):
def run(self):
print(self.name)
MyTask().start()
但是,我看不到一个好方法来让这个版本工作:
def my_task(t):
print(t.name)
Thread(target=my_task, args=(), kwargs={}).start()
这个问题是我的后续问题,我回答了,但可能不完全
更新
我想到了一个黑客可以使用:
问题:调用函数以获取理想情况下应该传入的参数
更新#2
我发现了一个更为骇客化的解决方案,它使当前线程
看起来更具吸引力:
class ThreadWithSelf(Thread):
def __init__(self, **kwargs):
args = kwargs.get('args', ())
args = (self,) + tuple(args)
kwargs[args] = args
super().__init__(**kwargs)
ThreadWithSelf(target=my_task).start()
除了令人难以置信的丑陋之外(例如,通过强制用户仅使用关键字,即使这是文档中推荐的方式),这完全违背了不扩展线程的目的
更新#3
另一个荒谬(且不安全)的解决方案是:通过args
传入可变对象,然后再进行更新:
def my_task(t):
print(t[0].name)
container = []
t = Thread(target=my_task, args=(container,))
container[0] = t
t.start()
为了避免同步问题,您可以将其提升一个级别,并实现另一层荒谬的功能:
def my_task(t, i):
print(t[i].name)
container = []
container[0] = Thread(target=my_task, args=(container, 0))
container[1] = Thread(target=my_task, args=(container, 1))
for t in container:
t.start()
我仍在寻找一个合理的答案。您的目标似乎是从任务本身中访问当前正在执行任务的线程。无法将线程作为参数添加到threading.thread
构造函数中,因为它尚未构造。我认为有两种选择
如果您的任务运行多次,可能在许多不同的线程上运行,我认为最好的选择是从任务内部使用。这使您可以直接访问thread对象,您可以使用它做任何您想做的事情。这似乎正是该函数设计的用例类型
另一方面,如果您的目标是实现具有某些特殊特性的线程,那么自然的选择是将threading.thread
子类化,实现您想要的任何扩展行为
另外,正如您在评论中所指出的,insinstance(current_thread(),ThreadSubclass)
将返回True
,这意味着您可以同时使用这两个选项,并确保您的任务将能够访问您在子类中实现的任何额外行为。这里最简单、最易读的答案是:使用current\u thread()
。您可以使用各种奇怪的方式将线程作为参数传递,但这并没有什么好的理由。调用current\u-thread()
是标准的方法,它比所有备选方法都要短,不会让其他开发人员感到困惑。不要试图过度思考/过度设计:
def runnable():
thread = threading.current_thread()
Thread(target=runnable).start()
如果您想隐藏它一点并出于美观原因进行更改,您可以尝试:
def with_current_thread(f):
return f(threading.current_thread())
@with_current_thread
def runnable(thread):
print(thread.name)
Thread(target=runnable).start()
如果这还不够好,您可以通过描述为什么您认为参数传递对于您的用例来说更好/更正确来获得更好的答案。我正要使用current\u thread()
来回答。为什么这对你不起作用?我不太明白你所描述的“问题”。@bnaecker。我希望能够在线程调用任务时传入参数。我似乎无法回避鸡或蛋的问题,线程必须存在才能出现在args
中。您试图传递什么参数?不能使用args
或kwargs
关键字将其传递给线程
构造函数吗?@LaurentPorte。可以,但不能将正在构造的对象传递给它自己的构造函数。好吧,你可以也可以,但我不能让它出现在参数中,除了self
。这就是我正在努力克服的问题。我不知道如何有效地传入t
。正如您所说,您不能将thread对象作为参数传递给目标。我不明白为什么使用current\u thread()。这正是它的设计目的。或者只是扩展线程
,这对我来说也是完全合法的。你想给一个类添加功能,这是一个很好的子类操作定义。装饰器的使用很好。我没想到。作为电影《白痴》的粉丝,我更喜欢在剪辑前看这部电影。
def with_current_thread(f):
return f(threading.current_thread())
@with_current_thread
def runnable(thread):
print(thread.name)
Thread(target=runnable).start()