2015-03-11 4 views
1

Когда я запускаю код ниже, он, кажется, перебирает только половину общего списка рабочих в списке. Затем он переходит к закрытию родительского процесса.Почему этот провал пропускает элементы в списке?

Я очень смущен, почему код ниже не повторяет все элементы в списке, возможно, я слишком долго смотрел на это, чтобы увидеть очевидное? Любая помощь будет оценена по достоинству.

Вот консоль.

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 
+0

Как вы убедитесь, что он не работает? –

+0

Эти 'try'' excepts' являются довольно сомнительной структурой кода. Захватывать исключения, подобные мне, немного меня пугают. – HavelTheGreat

+0

@TimCastelijns - Проверьте выше для вывода. – cph

ответ

2

Причина в том, что вы только итерации над частью из-за workers_to_be_restarted.remove(item). Это фактически удаляет следующий пункт в вашем списке, а не тот, который вы собираетесь удалить. Например:

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 

Как вы можете видеть, второй и четвертый рабочие удаляются во время прохода над другими. Чтобы устранить эту проблему, сделайте копию вашего списка и сначала проведите по ней. Я хотел бы заменить текущую строку с полным списком уступке ломтика, как это:

for item in workers_to_be_restarted[:]: 

Выход:

worker-1.14524 
worker-1.14526 
worker-1.14518 
worker-1.14528 
worker-1.14522 
+0

Спасибо большое! Я идиот! – cph

2

Это происходит, когда вы изменяете список, который вы итерация:

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] 
Смежные вопросы