2013-08-09 2 views
0
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Почему os.system и subprocess.call порождают так много процессов?

Эта программа логики часть хорошо.
Проблема в том, что при попадании 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 Выполнение этого действия ведет себя так?

+0

Можете ли вы записать достаточно информации, чтобы узнать, что такое 'sys.argv' в каждом случае? Потому что очевидная догадка заключается в том, что вы используете свой собственный скрипт, а не ту вещь, которую вы действительно хотите запустить. – abarnert

+0

Собственно, Scite - это тот, который передается sys.argv ($ (FilePath)). Он передает строку «C: \ mine \ .cs \ test.cs». Я создал второй fname_ext, чтобы я мог переключаться между ними при тестировании. Он выводит те же результаты, когда я запускаю csc.py, и когда я запускаю test.cs, поэтому я не думаю, что у меня работает собственный скрипт. Даже если бы это был тот же сценарий, результаты были бы одинаковыми независимо от значения аргумента оболочки. – Segfault

ответ

0

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

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

+0

Я чувствую себя очень глупо. Он работает, когда я переименовываю его в casc.py (бессмысленно). У меня был собственный скрипт, это было не так очевидно. @abarnet был частично прав. Он также будет запущен, если вы отмените регистрацию расширения .PY от% PATHEXT% (это бессмысленно, хотя). Если вы объедините оба ответа, вы получите полное объяснение. Спасибо. – Segfault

1

Проблема заключается в том, что ваш 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, но с несколькими дополнительными слоями, подбрасываемыми для хорошей оценки.)

+0

Я смущен. Когда я открываю вкладку test.cs и запускаю ее, SciTE передает путь к скрипту, то есть питон C: \ mine \ .py \ csc.py C: \ mine \ .cs \ test.cs. Не будет sys.argv [1] по-прежнему быть файловым путем (который использует скрипт), а sys.argv [0] - имя скрипта (csc.py). Я вижу третий элемент в списке, как это? – Segfault