os.system для вызова exe-файла, который находится в директории, имя которой содержит пробелы - PullRequest
12 голосов
/ 08 августа 2011

просто мой код выглядит следующим образом:

file = 'C:\\Exe\\First Version\\filename.exe'
os.system(file)

когда я запускаю эту программу, возникает ошибка windowserror, не удается найти указанный файл. Я обнаружил, что проблема связана с пробелами между «Первая версия». Так могу ли я найти способ обойти проблему?

PS: Что если переменная 'file' будет передана как arg в другую функцию?

Ответы [ 5 ]

15 голосов
/ 08 августа 2011

Расстановка кавычек по пути будет работать:

file = 'C:\\Exe\\First Version\\filename.exe'
os.system('"' + file + '"')

, но лучшим решением будет использование вместо этого модуля subprocess:

import subprocess
file = 'C:\\Exe\\First Version\\filename.exe'
subprocess.call([file])
2 голосов
/ 08 августа 2011

Попробуйте заключить его в двойные кавычки.

file = '"C:\\Exe\\First Version\\filename.exe"'
os.system(file)
0 голосов
/ 26 января 2019

Это правда, что os.system запустит двоичный файл с пробелами в пути, заключив этот путь в кавычки. (Это должно быть довольно очевидным решением, если вы привыкли использовать терминал.) Однако само по себе это не решает более болезненную проблему с этой функцией ... Как только вы это сделаете, вы можете запустить в трудности добавления аргументов в вашу команду ! (Ааа!)

Все текущие рекомендации теперь должны использовать модуль subprocess вместо этой старой, не одобренной функции. Можно также использовать shlx для преобразования плоских строк в списки для этих функций подпроцесса. Я тоже сталкивался с проблемами или трудностями в этих методах, о которых я не буду рассказывать ... Кроме того, иногда просто проще использовать os.system, когда все, что вам нужно, это тонкая оболочка над оболочкой, которая неявно отображает выходные потоки. на консоли, работает синхронно и т. д. Я уверен, что хотелось бы иметь встроенную функцию для выполнения команды на оболочке, как это, с абсолютно 0 разбором, переносом, абстрагированием ...

Поскольку нет встроенного без «фильтров», вот мой патч решения для os.system. Это взято из моей библиотеки с открытым исходным кодом. Это было проверено на Windows, Mac и Ubuntu Linux. Я знаю, что это не на 100% надежно, и это более сложный загар, на который можно было бы надеяться, но это не так уж плохо.

Когда вы вызываете эту _system() оболочку (передавая строку для выполнения), просто заключите свой длинный путь в кавычки и включите любые аргументы, которые нужны с кавычками и без них. На первом «токене» в команде это удалит кавычки и пробелы в пути на Mac или Linux. В Windows он использует «короткое имя», фактически решая, что это в данной среде. Эта часть кода немного сложнее. В основном он использует пакетный механизм для разрешения имен и отправляет результаты обратно через stderr с целью анализа того, что вы получите в противном случае для результатов Popen() на stdout. Здесь вы также можете использовать опцию рабочего каталога и сначала установить ее в качестве альтернативного решения.

Я думаю, что я включил весь импорт и определил, что вам нужно. Если я что-то пропустил (копирование и вставка спинов источника), дайте мне знать.

from os import system, getcwd, chdir
from subprocess import Popen, PIPE

import platform
__plat = platform.system()
IS_WINDOWS = __plat == "Windows"
IS_LINUX   = __plat == "Linux"
IS_MACOS   = __plat == "Darwin"

__SCRUB_CMD_TMPL = "{0}{1}"
__DBL_QUOTE      = '"'
__SPACE          = ' '
__ESC_SPACE      = '\\ '
if IS_WINDOWS :        
    __BATCH_RUN_AND_RETURN_CMD = ["cmd","/K"] # simply assuming cmd is on the system path... 
    __BATCH_ONE_LINER_TMPLT    = "{0} 1>&2\n" # the newline triggers execution when piped in via stdin
    __BATCH_ESCAPE_PATH_TMPLT  = 'for %A in ("{0}") do @echo %~sA' 
    from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW
    __BATCH_ONE_LINER_STARTUPINFO = STARTUPINFO()
    __BATCH_ONE_LINER_STARTUPINFO.dwFlags |= STARTF_USESHOWWINDOW 

def _system( cmd, wrkDir=None ):
    if wrkDir is not None:
        initWrkDir = getcwd()
        print( 'cd "%s"' % (wrkDir,) )
        chdir( wrkDir  )
    cmd = __scrubSystemCmd( cmd )        
    print( cmd )
    system( cmd ) 
    print('')
    if wrkDir is not None: chdir( initWrkDir )

def __scrubSystemCmd( cmd ):
    """
    os.system is more convenient than the newer subprocess functions
    when the intention is to act as very thin wrapper over the shell. 
    There is just one MAJOR problem with it: 
    If the first character in the command is a quote (to escape a long path
    to the binary you are executing), then the limited (undesirable) parsing 
    built into the function can all fall apart.  So, this scrub function
    solves that...  
    """    
    if not cmd.startswith( __DBL_QUOTE ): return cmd
    cmdParts    = cmd[1:].split( __DBL_QUOTE )
    safeBinPath = _escapePath( cmdParts[0] )
    args        = __DBL_QUOTE.join( cmdParts[1:] ) # (the leading space will remain)
    return __SCRUB_CMD_TMPL.format( safeBinPath, args ) 

def _escapePath( path ):
    if not IS_WINDOWS: return path.replace(__SPACE, __ESC_SPACE)     
    return( path if __SPACE not in path else        
            __batchOneLinerOutput( __BATCH_ESCAPE_PATH_TMPLT.format(path) ) )    

def __batchOneLinerOutput( batch ):
    cmd = __BATCH_ONE_LINER_TMPLT.format( batch )
    p = Popen( __BATCH_RUN_AND_RETURN_CMD, shell=False, 
               startupinfo=__BATCH_ONE_LINER_STARTUPINFO,
               stdin=PIPE, stdout=PIPE, stderr=PIPE )    
    # pipe cmd to stdin, return stderr, minus a trailing newline
    return p.communicate( cmd )[1].rstrip()  
0 голосов
/ 19 февраля 2018

Я использовал это:

import subprocess, shlex
mycmd='"C:\\Program Files\\7-Zip\\7z" x "D:\\my archive.7z" -o"D:\\extract folder" -aou'
subprocess.run(shlex.split(mycmd))
0 голосов
/ 08 августа 2011

Вы можете использовать короткое имя файла, в имени которого есть пробелы.

file = 'C:\\Exe\\FirstV~1\\filename.exe'
os.system(file)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...