2009-05-26 3 views
34

Есть ли простой способ запуска скрипта Python в Windows/Linux/OS X?Использование подпроцесса для запуска сценария Python в Windows

На двух последних, subprocess.Popen("/the/script.py") работает, но на Windows я получаю следующее сообщение об ошибке:

Traceback (most recent call last): 
    File "test_functional.py", line 91, in test_functional 
    log = tvnamerifiy(tmp) 
    File "test_functional.py", line 49, in tvnamerifiy 
    stdout = PIPE 
    File "C:\Python26\lib\subprocess.py", line 595, in __init__ 
    errread, errwrite) 
    File "C:\Python26\lib\subprocess.py", line 804, in _execute_child 
    startupinfo) 
WindowsError: [Error 193] %1 is not a valid Win32 application 

monkut's comment: The use case isn't clear. Why use subprocess to run a python script? Is there something preventing you from importing the script and calling the necessary function?

я писал быстрый скрипт для тестирования общей функциональности в Python-команды -line (для тестирования на разных платформах). В основном ему приходилось создавать кучу файлов во временной папке, запускать скрипт на этом и проверять, что файлы были переименованы правильно.

Я мог бы импортирован сценарий и называется функцией, но, поскольку она опирается на sys.argv и использует sys.exit(), я нуждался бы сделать что-то вроде ..

import sys 
import tvnamer 
sys.argv.append("-b", "/the/folder") 
try: 
    tvnamer.main() 
except BaseException, errormsg: 
    print type(errormsg) 

Кроме того, я хотел захватить стандартный вывод и stderr для отладки, если что-то пошло не так.

Конечно, лучший способ - написать сценарий с большей степенью тестирования, но сценарий в основном «сделан», и я делаю окончательную партию тестирования перед выпуском «1.0» (после чего Я собираюсь сделать переписывание/реструктуризацию, которая будет намного более сложной и более проверяемой)

В принципе, было легко просто запустить сценарий как процесс, после нахождения переменной sys.executable. Я бы написал это как shell-скрипт, но это не было бы кросс-платформенным. Окончательный сценарий можно найти here

+2

Вариант использования не ясен. Зачем использовать подпроцесс для запуска скрипта python? Есть ли что-то, препятствующее вам импортировать скрипт и вызывая нужную функцию? – monkut

+0

Имела ту же проблему при запуске модулей nodejs из python. subprocess.call ([r '.. \ nodejs \ npm'], shell = True) решил проблему. – Stefan

ответ

52

Просто найти sys.executable - полный путь к текущему исполняемому Python, который может быть использован для запуска сценария (вместо того, чтобы полагаться на shbang, который, очевидно, не работает на Windows)

import sys 
import subprocess 

theproc = subprocess.Popen([sys.executable, "myscript.py"]) 
theproc.communicate() 
+3

вы можете использовать 'subprocess.check_call ([sys.executable," myscript.py "])' вместо этого. – jfs

1

Когда вы используете скрипт python для окон в подпроцессе, вы должны использовать python перед именем скрипта. Попробуйте:

process = subprocess.Popen("python /the/script.py") 
4

Похоже, окна пытается запустить скрипт, используя свою собственную структуру EXE-файла, а не называть его, как

python /the/script.py 

Try,

subprocess.Popen(["python", "/the/script.py"]) 

Edit: "питон" будет должны быть на вашем пути.

+0

Установщик Windows python.org, похоже, не помещает команду «python» в PATH, и я думаю, что у нее будет суффикс .exe (который сломает другие платформы) – dbr

+0

ah, я думаю, что .exe сломает вещи , да .. – viksit

+0

Хм, кажется, вы можете исключить .exe в Windows, если он находится в PATH, но вам нужно вручную добавить Python к нему. – dbr

2

Вы используете разделитель путей, который зависит от платформы. Windows использует «\», а Unix использует «/».

+0

Хорошая точка, хотя в самом скрипте, вызвавшем ошибку, я использовал os.path.join() (хотя я должен был упомянуть об этом) – dbr

+5

Конечно, косая черта была действительной для Windows с доисторических времен и до сих пор, так что не проблема. –

+0

@romkyns не очень: subprocess.call ([r '.. \ nodejs \ npm'], shell = True) работает, а subprocess.call (['../ nodejs/npm'], shell = True) дает ' .. 'не распознается как внутренняя или внешняя команда – Stefan

20

Как об этом:

import sys 
import subprocess 

theproc = subprocess.Popen("myscript.py", shell = True) 
theproc.communicate()     # ^^^^^^^^^^^^ 

Это говорит subprocess использовать оболочку ОС, чтобы открыть свой сценарий, и работает на все, что вы можете просто запустить в cmd.exe.

Кроме того, это будет поиск PATH для «myscript.py» - что может быть желательно.

+0

Я думаю, что будет работать то же самое, если я вспомню правку shell = True просто прекратит подпроцесс от экранирования каких-либо специальных символов (так что «mycmd> somefile.txt» перенаправляет текст в файл somefile.txt, вместо того, чтобы пытаться выполнить файл под названием « mycmd> somefile.txt ") – dbr

+2

Вот ситуация, в которой эти два существенно отличаются. Предположим, что «myscript.py» находится в системе PATH, а не в текущем каталоге. Если вы используете «shell = True», скрипт будет найден в PATH, но если вы используете «sys.executable», это не будет. –

+0

Ahh Я вижу, что вы имеете в виду (хотя скрипт, который я пытался запустить, всегда будет находиться в текущем каталоге) – dbr

5

Да subprocess.Popen(cmd, ..., shell=True) работает как очарование. В Windows распознается расширение файла .py, поэтому для его обработки вызывается Python (на * NIX только обычная shebang). Окружение пути контролирует, видны ли вещи. Итак, первый аргумент Popen - это только имя скрипта.

subprocess.Popen(['myscript.py', 'arg1', ...], ..., shell=True) 
+0

'shell = True # не показывать командную строку, затем true, если false показать это' – YumYumYum

1

Например, чтобы выполнить следующие с командной строки или файла сЕРИЙНОГО мы можем использовать это:

C:\Python27\python.exe "C:\Program files(x86)\dev_appserver.py" --host 0.0.0.0 --post 8080 "C:\blabla\" 

То же самое сделать с Python, мы можем сделать это:

subprocess.Popen(['C:/Python27/python.exe', 'C:\\Program files(x86)\\dev_appserver.py', '--host', '0.0.0.0', '--port', '8080', 'C:\\blabla'], shell=True) 

или

subprocess.Popen(['C:/Python27/python.exe', 'C:/Program files(x86)/dev_appserver.py', '--host', '0.0.0.0', '--port', '8080', 'C:/blabla'], shell=True) 
Смежные вопросы