Python запускает команду в фоновом режиме и проверяет, работает ли она pid [duplicate]

Ответ , а также другие ответы правильные. Я собираюсь добавить к этим ответам решение, которое, я думаю, будет полезно. Я думаю, что это часто возникает при программировании. Следует отметить, что для коллекций (списки, наборы и т. Д.) Основной проблемой является добавление в коллекцию. Вот где вещи ломаются. Даже удаление в порядке.

В большинстве случаев мы можем использовать Collection, а не Collection, и это должен быть первый выбор. Однако я нахожу случаи, когда это непросто сделать. Он обсуждает вопрос о том, всегда ли это самое лучшее. Я представляю здесь класс DownCastCollection, который может преобразовать Collection в Collection (мы можем определить аналогичные классы для List, Set, NavigableSet, ..), которые будут использоваться, когда использование стандартного подхода очень неудобно. Ниже приведен пример того, как его использовать (мы могли бы также использовать Collection в этом случае, но я просто не могу проиллюстрировать использование DownCastCollection.

/**Could use Collection and that is the better choice. 
* But I am doing this to illustrate how to use DownCastCollection. **/

public static void print(Collection col){  
    for(Object obj : col){
    System.out.println(obj);
    }
}
public static void main(String[] args){
  ArrayList list = new ArrayList<>();
  list.addAll(Arrays.asList("a","b","c"));
  print(new DownCastCollection(list));
}

Теперь класс:

import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class DownCastCollection extends AbstractCollection implements Collection {
private Collection delegate;

public DownCastCollection(Collection delegate) {
    super();
    this.delegate = delegate;
}

@Override
public int size() {
    return delegate ==null ? 0 : delegate.size();
}

@Override
public boolean isEmpty() {
    return delegate==null || delegate.isEmpty();
}

@Override
public boolean contains(Object o) {
    if(isEmpty()) return false;
    return delegate.contains(o);
}
private class MyIterator implements Iterator{
    Iterator delegateIterator;

    protected MyIterator() {
        super();
        this.delegateIterator = delegate == null ? null :delegate.iterator();
    }

    @Override
    public boolean hasNext() {
        return delegateIterator != null && delegateIterator.hasNext();
    }

    @Override
    public  E next() {
        if(!hasNext()) throw new NoSuchElementException("The iterator is empty");
        return delegateIterator.next();
    }

    @Override
    public void remove() {
        delegateIterator.remove();

    }

}
@Override
public Iterator iterator() {
    return new MyIterator();
}



@Override
public boolean add(E e) {
    throw new UnsupportedOperationException();
}

@Override
public boolean remove(Object o) {
    if(delegate == null) return false;
    return delegate.remove(o);
}

@Override
public boolean containsAll(Collection c) {
    if(delegate==null) return false;
    return delegate.containsAll(c);
}

@Override
public boolean addAll(Collection c) {
    throw new UnsupportedOperationException();
}

@Override
public boolean removeAll(Collection c) {
    if(delegate == null) return false;
    return delegate.removeAll(c);
}

@Override
public boolean retainAll(Collection c) {
    if(delegate == null) return false;
    return delegate.retainAll(c);
}

@Override
public void clear() {
    if(delegate == null) return;
        delegate.clear();

}

}

30
задан DavidJB 18 April 2013 в 00:15
поделиться

2 ответа

Вы должны использовать subprocess.Popen вместо subprocess.call.

Что-то вроде:

subprocess.Popen(["python", "slave.py"] + sys.argv[1:])

Из документов в subprocess.call :

Запустите команду, описанную args. Подождите, пока команда завершится, а затем верните атрибут returncode.

(Также не используйте список для передачи в аргументах, если вы собираетесь использовать shell = True).


Вот пример MCVE1, демонстрирующий неблокирующий вызов суперпроцесса:

import subprocess
import time

p = subprocess.Popen(['sleep', '5'])

while p.poll() is None:
    print('Still sleeping')
    time.sleep(1)

print('Not sleeping any longer.  Exited with returncode %d' % p.returncode)

Альтернативный подход, основанный на более поздних изменениях языка python для обеспечения совместного использования основанный на параллелизме:

# python3.5 required but could be modified to work with python3.4.
import asyncio

async def do_subprocess():
    print('Subprocess sleeping')
    proc = await asyncio.create_subprocess_exec('sleep', '5')
    returncode = await proc.wait()
    print('Subprocess done sleeping.  Return code = %d' % returncode)

async def sleep_report(number):
    for i in range(number + 1):
        print('Slept for %d seconds' % i)
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()

tasks = [
    asyncio.ensure_future(do_subprocess()),
    asyncio.ensure_future(sleep_report(5)),
]

loop.run_until_complete(asyncio.gather(*tasks))
loop.close()

1 Проверено на OS-X с использованием python2.7 & amp; python3.6

33
ответ дан Dan D. 24 August 2018 в 20:55
поделиться

Здесь три уровня тщательности.

Как утверждает Миллилсон, если вы просто замените subprocess.call на subprocess.Popen, оставив все остальное одинаковым, то main.py не будет ждать ведомого. чтобы закончить до его продолжения. Этого может быть достаточно. Если вы заботитесь о зомби-процессах , висящих вокруг, вы должны сохранить объект, возвращенный из subprocess.Popen, а в какой-то более поздний момент вызывать его метод wait. (Зомби автоматически уйдут, когда main.py выйдет, поэтому это серьезная проблема, если main.py работает очень долго и / или может создавать много подпроцессов.) И, наконец, если вы не хотите зомби но вы также не хотите решать, где делать ожидание (это может быть целесообразно, если оба процесса запускаются в течение длительного и непредсказуемого времени после этого), используйте библиотеку python-daemon , чтобы подчинить подчиненную функцию disassociate сам от мастера - в этом случае вы можете продолжить использование subprocess.call в главном устройстве.

18
ответ дан zwol 24 August 2018 в 20:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: