Выполнять команды последовательно в Python?

Я хотел бы выполнить несколько команд подряд:

то есть (просто чтобы проиллюстрировать мою потребность):

cmd (оболочка)

тогда

cd dir

а также

ls

и прочитайте результат ls.

Есть идеи с модулем subprocess?

Обновление:

cd dir и ls — это просто пример. Мне нужно запускать сложные команды (в определенном порядке, без какой-либо конвейерной обработки). На самом деле хотелось бы одну оболочку подпроцесса и возможность запускать на ней множество команд.


person MechanTOurS    schedule 11.12.2008    source источник
comment
возможно, вам следует написать сценарий оболочки вместо сценария python   -  person    schedule 11.12.2008


Ответы (5)


Существует простой способ выполнить последовательность команд.

Используйте следующее в subprocess.Popen

"command1; command2; command3"

Или, если вы застряли с окнами, у вас есть несколько вариантов.

  • Создайте временный файл ".BAT" и предоставьте его subprocess.Popen

  • Создайте последовательность команд с разделителями «\n» в одной длинной строке.

Используйте """, например.

"""
command1
command2
command3
"""

Или, если вы должны делать что-то по частям, вы должны сделать что-то вроде этого.

class Command( object ):
    def __init__( self, text ):
        self.text = text
    def execute( self ):
        self.proc= subprocess.Popen( ... self.text ... )
        self.proc.wait()

class CommandSequence( Command ):
    def __init__( self, *steps ):
        self.steps = steps
    def execute( self ):
        for s in self.steps:
            s.execute()

Это позволит вам построить последовательность команд.

person S.Lott    schedule 11.12.2008
comment
subprocess.Popen("ls") работает. Однако subprocess.Popen("ls; ls") не работает для меня. Ошибка: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib64/python2.6/subprocess.py", line 639, in __init__ errread, errwrite) File "/usr/lib64/python2.6/subprocess.py", line 1228, in _execute_child raise child_exception OSError: [Errno 2] No such file or directory - person Xander Dunn; 18.09.2012
comment
Это не удалось, потому что Popen ожидает список в качестве своего первого аргумента, а просто ls эквивалентен [ls]. Он пытается найти исполняемый файл с именем ls; ls, которого явно нет. - person Jatin Kumar; 09.12.2014
comment
Разве выполнение из класса CommandSequence не перекрывает выполнение () из класса Command? Если да, то как работает s.execute? - person user97662; 26.03.2015
comment
отсутствие shell=True вызвало у меня ту же проблему def do_shell(self, command): self.proc=subprocess.Popen(command,shell=True) self.proc.wait() - person Neil McGill; 14.05.2015
comment
Код даже не тестировался - person MaxBlax360; 16.05.2017
comment
Использование s = """my script with line break""" и запуск его с subprocess.run([s], shell=True) хорошо сработали для меня. - person Izaya; 12.11.2020

Для этого вам нужно:

  • предоставить аргумент shell=True в вызове subprocess.Popen и
  • separate the commands with:
    • ; if running under a *nix shell (bash, ash, sh, ksh, csh, tcsh, zsh etc)
    • & при работе под cmd.exe Windows
person tzot    schedule 11.12.2008
comment
Или для окон можно использовать &&, чтобы команда, выдавшая ошибку, предотвратила выполнение команд после нее. - person twasbrillig; 27.01.2014
comment
@twasbrillig Интересно; Я не знал, что cmd.exe разделяет этот разделитель команд с оболочками Unix. Я должен обновить свои знания. Спасибо! - person tzot; 27.01.2014
comment
Спасибо, это бесценно и было действительно трудно найти. - person CodeMonkey; 11.07.2017

Поиск «bar» в каждом файле, имя которого содержит «foo»:

from subprocess import Popen, PIPE
find_process = Popen(['find', '-iname', '*foo*'], stdout=PIPE)
grep_process = Popen(['xargs', 'grep', 'bar'], stdin=find_process.stdout, stdout=PIPE)
out, err = grep_process.communicate()

'out' и 'err' — это строковые объекты, содержащие стандартный вывод и, в конце концов, вывод ошибки.

person Oli    schedule 11.12.2008

Да, функция subprocess.Popen() поддерживает аргумент ключевого слова cwd, с помощью которого вы можете указать каталог, в котором он запускает процесс.

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

Конечно, вы также можете просто передать нужный каталог в качестве аргумента ls.

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

person unwind    schedule 11.12.2008

ниже скрипт python имеет 3 функции, которые вы просто выполнили:

import sys
import subprocess

def cd(self,line):
    proc1 = subprocess.Popen(['cd'],stdin=subprocess.PIPE)
    proc1.communicate()

def ls(self,line):
    proc2 = subprocess.Popen(['ls','-l'],stdin=subprocess.PIPE)
    proc2.communicate()

def dir(silf,line):
    proc3 = subprocess.Popen(['cd',args],stdin=subprocess.PIPE)
    proc3.communicate(sys.argv[1])
person Community    schedule 03.10.2015
comment
это неправильно. cd не влияет на родителя, и вполне вероятно, что OP хочет, чтобы команда была встроена в оболочку (Popen() не запускает оболочку, если вы не попросите явно - хотя в этом случае это не поможет). - person jfs; 04.10.2015