Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从线程目标访问“self”_Python_Multithreading_Python 3.x - Fatal编程技术网

Python 从线程目标访问“self”

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

根据许多来源,包括,将runnable作为
目标
参数传入(带或不带
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()