Почему os.system и subprocess.call порождают так много процессов?

import os
import subprocess
import sys
import re

## fname_ext=sys.argv[1]
fname_ext=r"C:\mine\.cs\test.cs"
exe=os.path.splitext(fname_ext)[0]+".exe" # Executable
fdir=os.path.split(fname_ext)[0]
fcontent=open(fname_ext).read()

p_using=re.compile("\s*using\s+((\w+[.]*)+)")
p_namespace=re.compile("\s*namespace\s+(\w+)")
usings=p_using.findall(fcontent)
usings=[x[0] for x in usings]
references=[]
for i in os.listdir(fdir):
    path=fdir+"\\"+i
    try:
        if os.path.isdir(path) or (not path.endswith('cs')):continue
        with open(path) as fp:
            content=fp.read()
            namespaces=p_namespace.findall(content)
            for n in namespaces:
                if n in usings and 'System' not in n:
                    references+=[path]
    except:
        pass

command="csc /nologo "+" ".join(references)+" "+fname_ext
## command=" ".join(references)
#~ ---------------------------------------------------------
# Build:
option=1
if option==0:
    # using os.system
    print ">>",command
    if os.system(command)==0:
        os.system(exe)
else:
    #~ Using subprocess module
    ## print type(references)
    command=['csc']
    ## print command,references
    command.extend(["/nologo","/out:"+exe])
    command.extend(references)
    command.append(fname_ext)
    ## print command
    if subprocess.call(command,shell=True)==0:
        ## print "running %s"%exe
        subprocess.call([exe],shell=True)
    else:
        pass
        ## print "Failed to run"
#~ ---------------------------------------------------------

У меня есть этот код выше, который должен запускать программу Csharp из SciTE, Ищет
каждый .cs файл в каталоге и находит файл с пространством имен, что текущий
файл включен. Команда для запуска файла в SciTE:
command.go.*.cs=python C:\mine\.py\csc.py $(FilePath)
command.go.subsystem.*.cs=0

Эта логическая часть программы в порядке.
Проблема в том, что при нажатии F5 с примером кода Csharp, как это:

using System;
using System.Collections;
using MyNamespace;
class Test{
    public static void Main(String[] args){
        MyObject inst=new MyObject();
        MyObject.self_destruct(inst);
    }
}

все работает нормально. Но когда я раскомментирую второй fname_ext и прокомментируй первый
и запустите файл csc.py, откроется окно и продолжит работу, печать command (Бывает
с использованием os.system опция). Когда вы используете the subprocess.call вариант, тоже самое
бывает, но на этот раз только когда shell=True, Он работал всего 15 секунд, и было более 800 процессов cmd.exe и python.exe. Мне пришлось ждать почти 5 минут после убийства cmd.exe
для мыши, чтобы начать отвечать и еще 2 минуты для рабочего стола.
когда shell=False, он работает нормально, так же, как когда вы нажмете клавишу F5 из файла.
Что здесь происходит?
Что такое shell=True что заставляет его так себя вести?

2 ответа

Решение

Ладно, я попробую. Если я понимаю ситуацию, этот скрипт называется csc.py, и вы хотите вызвать компилятор csc C#. Когда ты бежишь csc /nologo (etc...) через cmd.exe он начинает искать что-то с именем "csc" с известным расширением. Он находит csc.py в текущем каталоге и, так как.py является зарегистрированным расширением, это то, что исполняется.

Решение состоит в том, чтобы переименовать ваш файл python или явно вызвать csc.exe.

Проблема в том, что ваш sys.argv выглядит примерно так:

['python', r'C:\mine\.py\csc.py', 'whatever.cs']

Итак, с fname_ext строка без комментариев, вы установили fname_ext в r'C:\mine\.py\csc.py', Это означает, что ваш скрипт в конечном итоге просто запускается сам - который снова запускается сам и т. Д., Настолько быстро, насколько это возможно, пока ваша система не задохнется.

Причина, по которой это не происходит с shell=False в том, что вы не можете выполнить скрипт Python. В конечном итоге вы звоните CreateProcess с вашим сценарием, который пытается интерпретировать его как файл.exe, завершается неудачно и возвращает ошибку. Но с shell=True Вы передаете свой сценарий cmd.exe запускается как программа, и она делает то же самое, что и интерактивная подсказка или Проводник: находит правильное отображение для выполнения файлов.py и использует его. (А также os.system эффективно делает то же самое, что и shell=True, но с парой дополнительных слоев, добавленных для хорошей меры.)

Другие вопросы по тегам