简体   繁体   English

将 *args 或 **kwargs 传入 threading.Thread()

[英]Passing *args or **kwargs into threading.Thread()

Using the threading library, I am attempting to pass down a variety of args/keyword args into the threading function.使用线程库,我试图将各种参数/关键字参数传递到线程函数中。 There are three different situations.存在三种不同的情况。 Each one consists of a function ran prior to the threading function, which passes down the options to the threading function to tell it what function to call for the threading, and the arguments.每一个都包含一个在线程函数之前运行的函数,它将选项传递给线程函数以告诉它调用线程的哪个函数,以及参数。 In some situations, there will be keyword arguments, in some arguments, and in some, none.在某些情况下,会有关键字参数,在某些参数中,而在某些情况下,没有。 Here is the sample code of the threading function:下面是线程函数的示例代码:

def create_some_threads(my_target, *my_args, **my_keyword_args):
        for DeviceName in Devices:
            device_ip = Devices[DeviceName]['mgmt_ip']
            my_thread = threading.Thread(target=my_target, args=(device_ip, DeviceName, *my_args, **my_keyword_args))
            my_thread.start()

Unfortunately, I get the error:不幸的是,我收到错误:

    my_thread = threading.Thread(target=my_target, args=(device_ip, DeviceName, *args, **kwargs))
                                                                                ^                                                                
SyntaxError: invalid syntax

Here is the function where I call in the *my_args:这是我在 *my_args 中调用的函数:

pingable_devices = {}
unpingable_devices = {}
with open(os.devnull, "wb") as limbo:
    print("\n[+] Progress:\n")
    pbar = tqdm(total=100)
    my_args = (pingable_devices, unpingable_devices, pbar, limbo)
    my_target = ping_em_all
    create_some_threads(my_target, *my_args)

The problem is, for each function I use prior to calling the threading function, there are a different set of arguments/keyword arguments that I will call.问题是,对于我在调用线程函数之前使用的每个函数,我将调用一组不同的参数/关键字参数。 I attempted to make this a function on its own, but if I can't run it something like this, then I may have to explore other avenues.我试图让它自己成为一个函数,但如果我不能像这样运行它,那么我可能不得不探索其他途径。

Edit: This first problem was solved by unutbu, but now I have encountered a second problem.编辑:第一个问题由 unutbu 解决,但现在我遇到了第二个问题。 It seems the function called by the threading function is not recognizing the variables passed into threading, my_args.线程函数调用的函数似乎无法识别传递给线程函数 my_args 的变量。 Error is below:错误如下:

Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "Automatelab.py", line 157, in ping_em_all
    ping_reply = subprocess.Popen(['ping', '-c', '2', '-w', '2', '-q', device_ip.rstrip('\n')],stdout=limbo, stderr=limbo).wait()
NameError: global name 'device_ip' is not defined

Here is the ping_em_all function:这是 ping_em_all 函数:

def ping_em_all(*my_args, **my_keyword_args):
    """.rstrip is needed for the ip as .readline adds a \n to
    the lines' text"""
    if "Linux" in platform.system():
        ping_reply = subprocess.Popen(['ping', '-c', '2', '-w', '2', '-q', device_ip.rstrip('\n')],stdout=limbo, stderr=limbo).wait()
    #Darwin is Mac OSX
    elif "Darwin" in platform.system():
        ping_reply = subprocess.Popen(['ping', '-c', '2', '-t', '2', '-q', '-n', device_ip.rstrip('\n')],stdout=limbo, stderr=limbo).wait()
        """Subprocess for Cygwin still not supported"""
    else:
    #Only other would be Windows
        ping_reply = subprocess.Popen(['ping', '-n', '2', '-w', '2', device_ip.rstrip('\n')],stdout=limbo, stderr=limbo).wait()

The target is called with :目标被调用

self._target(*self._args, **self._kwargs)

Therefore, you could use:因此,您可以使用:

def create_some_threads(my_target, *my_args, **my_keyword_args):
    for DeviceName in Devices:
        device_ip = Devices[DeviceName]['mgmt_ip']
        my_args = (device_ip, DeviceName,) + my_args
        my_thread = threading.Thread(target=my_target, 
                                     args=my_args, kwargs=my_keyword_args))
        my_thread.start()

When you define you define a function with *my_args or **my_keyword_args in its call signature, note that my_args becomes a tuple inside the body of that function, and my_keyword_args becomes a dict.在定义函数时,在其调用签名中使用*my_args**my_keyword_args定义函数,请注意my_args成为该函数体内的元组,而my_keyword_args成为字典。

my_args = (device_ip, DeviceName,) + my_args

simply concatenates two more values to the front of the my_args tuple.简单地将另外两个值连接到my_args元组的前面。


The error message错误信息

NameError: global name 'device_ip' is not defined

is saying that the variable name device_ip has not been defined in a scope that is accessible at the point where the NameError occurred.是说变量名称device_ip尚未发生NameError可访问的范围内定义。 A look at the ping_em_all function shows that that's true:查看ping_em_all函数表明这是真的:

def ping_em_all(*my_args, **my_keyword_args):
    """.rstrip is needed for the ip as .readline adds a \n to
    the lines' text"""
    if "Linux" in platform.system():
        ping_reply = subprocess.Popen(['ping', '-c', '2', '-w', '2', '-q', device_ip.rstrip('\n')],stdout=limbo, stderr=limbo).wait()
    ...            

device_ip is the first value in my_args : device_ipmy_args的第一个值:

my_args = (device_ip, DeviceName,) + my_args

Therefore, change ping_em_all to因此,将ping_em_all更改为

def ping_em_all(*my_args, **my_keyword_args):
    """.rstrip is needed for the ip as .readline adds a \n to
    the lines' text"""
    device_ip, DeviceName, my_args = my_args    #<-- This defines device_ip
    if "Linux" in platform.system():
        ping_reply = subprocess.Popen(['ping', '-c', '2', '-w', '2', '-q', device_ip.rstrip('\n')],stdout=limbo, stderr=limbo).wait()
    ...            

to unpack values from the my_args tuple and give them variable names.my_args元组中解压值并给它们变量名。

There are a few possible issues I see.我看到了一些可能的问题。

In this line:在这一行:

my_thread = threading.Thread(target=my_target, args=(device_ip, DeviceName, *my_args, **my_keyword_args))

You don't need the asterisks in front of *my_args and **my_keyword_args The asterisk goes in the function parameters but inside of the function you can just refer to them as my_args or my_keyword_args .您不需要*my_args**my_keyword_args的星号 星号位于函数参数中,但在函数内部,您可以将它们称为my_argsmy_keyword_args Secondly, for the args parameter, you can remove the my_keyword_args from that and instead put it at the end.其次,对于args参数,您可以从中删除my_keyword_args并将其放在最后。 Here's a basic format to help clarify:这是帮助澄清的基本格式:

import threading

def start_thread(function_name, *args, **kwargs):
    t = threading.Thread(target=function_name, args=args, kwargs=kwargs)
    t.daemon = True
    t.start()

def this_and_that(input_data, started=False, finished=False):
    for i in names_list:
        if started is True and finished is False:
            print(i, started, finished)
        elif started is True and finished is True:
            print(i, started, finished)
        else:
            print(i, started, finished)

n = ['Steve','Smith']

start_thread(this_and_that, n, started=True, finished=True)

Output looks like this:输出如下所示:

Steve True True
Smith True True

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

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