为什么这个 forloop 会跳过列表中的项目?
Why is this forloop skipping items in the list?
当我运行下面的代码时,它似乎只遍历了列表中所有工人列表的一半。然后它跳转到关闭父进程。
我非常困惑,为什么下面的代码没有遍历列表中的所有项目,也许我盯着这个看得太久了,看不出明显的东西?任何帮助将不胜感激。
这是控制台输出。
Waiting...
[u'worker-1.15579', u'worker-1.15575', u'worker-1.15577', u'worker-1.15570', u'worker-1.15573', u'worker-1.15168', u'worker-1.15170']
The terminate_pid is 15561
Process was SUCCESSFULLY closed.
Process was SUCCESSFULLY closed.
Process was SUCCESSFULLY closed.
no process found with pid 15170
Process was already closed.
Closed terminator window.
下面是代码,
workers_to_be_restarted = [u'worker-1.14524', u'worker-1.14526', u'worker-1.14518', u'worker-1.14528', u'worker-1.14522']
for item in workers_to_be_restarted:
if this_machine == item.split('.')[0]:
if not terminate_pid:
try:
terminate_pid = psutil.Process(psutil.Process( int(item.split('.')[1]) ).ppid()).ppid()
print "The terminate_pid is {}".format(str(terminate_pid))
except Exception, e:
terminate_pid = None
print e
pass
try:
print "Terminating {}".format(item)
p = psutil.Process( int(item.split('.')[1]) )
p.terminate()
time.sleep(1)
print "Process was SUCCESSFULLY closed."
workers_to_be_restarted.remove( item )
except Exception, e:
print e
time.sleep(1)
print "Process was already closed."
workers_to_be_restarted.remove( item )
pass
try: #THE ABOVE SEEMS TO BE EXITING HERE before looping through all the items!? NOT SURE WHY?
if terminate_pid:
p = psutil.Process( terminate_pid )
p.terminate()
print "Closed terminator window."
worker_restart['restart'] = None
worker_restart['workers_to_be_restarted'] = workers_to_be_restarted
当您修改正在迭代的列表时会发生这种情况:
foo = [1, 2, 3, 4, 5]
for each in foo:
if each == 2:
foo.remove(each)
print each
>>> 1
>>> 2
>>> 4
>>> 5
要解决这个问题,您可以将列表复制到一个新列表中,然后从副本(而不是您正在迭代的那个)中删除:
foo = [1, 2, 3, 4, 5]
bar = list(foo)
for each in foo:
if each == 2:
bar.remove(each)
print each
print bar
>>> 1
>>> 2
>>> 3
>>> 4
>>> 5
>>> [1, 3, 4, 5]
看起来您只是在迭代一部分的原因是 workers_to_be_restarted.remove( item )
。这实际上是删除列表中的 next 项目,而不是您打算删除的项目。例如:
workers_to_be_restarted = [u'worker-1.14524', u'worker-1.14526', u'worker-1.14518', u'worker-1.14528', u'worker-1.14522']
for item in workers_to_be_restarted:
print(item)
workers_to_be_restarted.remove(item)
输出:
worker-1.14524
worker-1.14518
worker-1.14522
如您所见,第二个和第四个工人在迭代其他工人时被删除。
要解决此问题,请先 copy 列表并对其进行迭代。我会用这样的完整列表切片分配替换您当前的行:
for item in workers_to_be_restarted[:]:
输出:
worker-1.14524
worker-1.14526
worker-1.14518
worker-1.14528
worker-1.14522
当我运行下面的代码时,它似乎只遍历了列表中所有工人列表的一半。然后它跳转到关闭父进程。
我非常困惑,为什么下面的代码没有遍历列表中的所有项目,也许我盯着这个看得太久了,看不出明显的东西?任何帮助将不胜感激。
这是控制台输出。
Waiting...
[u'worker-1.15579', u'worker-1.15575', u'worker-1.15577', u'worker-1.15570', u'worker-1.15573', u'worker-1.15168', u'worker-1.15170']
The terminate_pid is 15561
Process was SUCCESSFULLY closed.
Process was SUCCESSFULLY closed.
Process was SUCCESSFULLY closed.
no process found with pid 15170
Process was already closed.
Closed terminator window.
下面是代码,
workers_to_be_restarted = [u'worker-1.14524', u'worker-1.14526', u'worker-1.14518', u'worker-1.14528', u'worker-1.14522']
for item in workers_to_be_restarted:
if this_machine == item.split('.')[0]:
if not terminate_pid:
try:
terminate_pid = psutil.Process(psutil.Process( int(item.split('.')[1]) ).ppid()).ppid()
print "The terminate_pid is {}".format(str(terminate_pid))
except Exception, e:
terminate_pid = None
print e
pass
try:
print "Terminating {}".format(item)
p = psutil.Process( int(item.split('.')[1]) )
p.terminate()
time.sleep(1)
print "Process was SUCCESSFULLY closed."
workers_to_be_restarted.remove( item )
except Exception, e:
print e
time.sleep(1)
print "Process was already closed."
workers_to_be_restarted.remove( item )
pass
try: #THE ABOVE SEEMS TO BE EXITING HERE before looping through all the items!? NOT SURE WHY?
if terminate_pid:
p = psutil.Process( terminate_pid )
p.terminate()
print "Closed terminator window."
worker_restart['restart'] = None
worker_restart['workers_to_be_restarted'] = workers_to_be_restarted
当您修改正在迭代的列表时会发生这种情况:
foo = [1, 2, 3, 4, 5]
for each in foo:
if each == 2:
foo.remove(each)
print each
>>> 1
>>> 2
>>> 4
>>> 5
要解决这个问题,您可以将列表复制到一个新列表中,然后从副本(而不是您正在迭代的那个)中删除:
foo = [1, 2, 3, 4, 5]
bar = list(foo)
for each in foo:
if each == 2:
bar.remove(each)
print each
print bar
>>> 1
>>> 2
>>> 3
>>> 4
>>> 5
>>> [1, 3, 4, 5]
看起来您只是在迭代一部分的原因是 workers_to_be_restarted.remove( item )
。这实际上是删除列表中的 next 项目,而不是您打算删除的项目。例如:
workers_to_be_restarted = [u'worker-1.14524', u'worker-1.14526', u'worker-1.14518', u'worker-1.14528', u'worker-1.14522']
for item in workers_to_be_restarted:
print(item)
workers_to_be_restarted.remove(item)
输出:
worker-1.14524
worker-1.14518
worker-1.14522
如您所见,第二个和第四个工人在迭代其他工人时被删除。 要解决此问题,请先 copy 列表并对其进行迭代。我会用这样的完整列表切片分配替换您当前的行:
for item in workers_to_be_restarted[:]:
输出:
worker-1.14524
worker-1.14526
worker-1.14518
worker-1.14528
worker-1.14522