使用线程库,我试图将各种args / keyword args传递给线程函数。有三种不同的情况。每个函数都包含一个在线程函数之前运行的函数,该函数将选项传递给线程函数,以告诉它为线程调用的函数和参数。在某些情况下,在某些参数中会有关键字参数,在某些参数中会有。以下是线程函数的示例代码:
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()
不幸的是,我收到错误:
my_thread = threading.Thread(target=my_target, args=(device_ip, DeviceName, *args, **kwargs))
^
SyntaxError: invalid syntax
这是我在* 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)
问题是,对于我在调用线程函数之前使用的每个函数,我将调用一组不同的参数/关键字参数。我试图让它自己成为一个功能,但如果我不能像这样运行它,那么我可能需要探索其他途径。
编辑:第一个问题是由unutbu解决的,但现在我遇到了第二个问题。似乎线程函数调用的函数没有识别传递给线程的变量my_args。错误如下:
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
这是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()
答案 0 :(得分:1)
目标是called with:
self._target(*self._args, **self._kwargs)
因此,您可以使用:
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()
当您定义在其调用签名中定义*my_args
或**my_keyword_args
的函数时,请注意my_args
成为该函数正文中的元组,my_keyword_args
成为一个字典。
my_args = (device_ip, DeviceName,) + my_args
简单地将另外两个值连接到my_args
元组的前面。
错误消息
NameError: global name 'device_ip' is not defined
表示在device_ip
发生的位置尚未定义变量名NameError
in a scope that is accessible。查看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
是my_args
中的第一个值:
my_args = (device_ip, DeviceName,) + my_args
因此,请将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()
...
从my_args
元组中解压缩值并为其赋予变量名称。
答案 1 :(得分:0)
我看到了一些可能的问题。
在这一行:
my_thread = threading.Thread(target=my_target, args=(device_ip, DeviceName, *my_args, **my_keyword_args))
您不需要在*my_args
和**my_keyword_args
前面加上星号,但是在函数内部可以将它们称为my_args
或{ {1}}。其次,对于my_keyword_args
参数,您可以从中删除args
并将其放在最后。这是有助于澄清的基本格式:
my_keyword_args
输出看起来像这样:
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)