Python - Windows - Popen(shlex.split(command), shell=False причинява OSError: [Errno 2] Няма такъв файл или директория

Изпълнявам този код, който работи добре в OSX, но причинява грешка в Windows:

command = "C:\\progra~2\\itms\\iTMSTransporter -m verify -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"
self.process1 = Popen(shlex.split(command), shell=False, stdin=PIPE)

Грешката, която получавам в Windows е:

WindowsError: [Error 2] The system cannot find the file specified

Защо ми дава тази грешка в Windows?


person speedyrazor    schedule 22.05.2014    source източник
comment
Опитвате се да изпълните команда, като посочите пътя до изпълним файл. /usr/local/itms/share/iTMSTransporter.woa/iTMSTransporter е път във файлова система. В Windows пътищата на файловата система започват с буква на устройство. Няма начин това да е валиден път в Windows. Оттук и грешката, която е доста ясна, бих казал.   -  person Dr. Jan-Philip Gehrcke    schedule 22.05.2014
comment
Съжалявам, прав си! Исках да променя пътя на път на Windows, което направих. Актуализирах въпроса.   -  person speedyrazor    schedule 22.05.2014
comment
трябва да излезете от командата и да не използвате тилда: команда = \C:\\program files\\itms\\iTMSTransporter.exe\ ...   -  person Leonardo Bernardini    schedule 22.05.2014
comment
Системата ви казва, че пътят все още е грешен. Не съм сигурен за съобщенията за грешка на Windows тук, но съм почти сигурен, че ако проблемът е, че файлът не може да бъде достъпен или не може да бъде изпълнен, тогава съобщението за грешка ще бъде различно. Вероятно низът progra~2 е невалиден.   -  person Dr. Jan-Philip Gehrcke    schedule 22.05.2014
comment
progra~2 работи добре с shell=Вярно, все още не мога да го накарам да работи.   -  person speedyrazor    schedule 22.05.2014
comment
Леонардо, опитах command = \C:\\program files\\itms\\iTMSTransporter.exe\, но пак получавам същата грешка.   -  person speedyrazor    schedule 22.05.2014


Отговори (2)


Вашият shlex.split() унищожава пътя ви поради премахване на символи \. Да проверим:

import shlex
command = "C:\\progra~2\\itms\\iTMSTransporter -m verify -f  Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"
print shlex.split(command)

['C:progra~2itmsiTMSTransporter', '-m', 'verify', '-f', '/Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp', '-u', 'username', '-p', 'password', '-o', '/Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt', '-s', 'provider', '-v', 'eXtreme']

Както можете да видите, пътят до изпълним файл е неправилен (C:progra~2itmsiTMSTransporter), така че Popen не може да го намери.

Променете разделителя на пътя на /, което е безопасно и в двете Linux/Windows среди:

command = "C:/progra~2/itms/iTMSTransporter -m verify -f  Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"
print shlex.split(command)

['C:/progra~2/itms/iTMSTransporter', '-m', 'verify', '-f', 'Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp', '-u', 'username', '-p', 'password', '-o', '/Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt', '-s', 'provider', '-v', 'eXtreme']

Popen() ще обработи този път правилно.

person Gabriel M    schedule 22.05.2014
comment
Опитах горното предложение, но все още получавам същата грешка. Някакви идеи, моля? - person speedyrazor; 24.05.2014

Това може да дойде малко късно, но може би е полезно за други, които имат подобни проблеми.

Преди да започнем: обикновено съм склонен да използвам необработени низове, когато обработвам пътища на Windows, за да улесня поставянето на копиране, тъй като приема единични знаци с обратна наклонена черта:

In [0]: "C:\\path\\to\\folder" == r"C:\path\to\folder"
Out[0]: True

Както бе споменато в отговора на Gabriel M, проблемът може да идва от shlex преглъщане на обратната реакция. В този отговор искам да осигуря решение, различно от замяната на обратните наклонени черти с наклонени черти.

In [1]: import shlex

In [2]: command = r"C:\progra~2\itms\iTMSTransporter -m verify 
   ...: -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password
   ...: -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"

In [3]: shlex.split(command)[0]
Out[3]: 'C:progra~2itmsiTMSTransporter'

Просто решение за запазване на обратните наклонени черти е да прехвърлите опцията posix=False на shlex.split():

In [4]: shlex.split(command, posix=False)[0]
Out[4]: 'C:\\progra~2\\itms\\iTMSTransporter'

Както посочихте в коментарите на другия отговор, замяната на наклонени черти не реши проблема ви, възможно е действителният ви проблем да се крие в пътищата, които предавате на вашия скрипт в -f и -o. Може би за скрипт подавате тези пътеки към очаква символи с обратна наклонена черта или искате да имате буквата на устройството в пътя. – Както и да е, би било интересно дали сте намерили решение за него през последните 6 години и какво беше това решение.


Допълнителни опции

Можете също да използвате pathlib (стандартна библиотека на python3 за форматиране на пътя, съобразен с ОС), който Path предоставя as_posix() метод за преобразуване на пътя в низ с наклонени черти. Това ще доведе до наклонени черти във вашия shlex.split() изход. Това може да е най-полезно, ако вашият път идва от променлива и не е директно кодиран (в последния случай може просто да промените (обратните) наклонени черти):

In [5]: from pathlib import Path

In [6]: command = Path(r"C:\progra~2\itms\iTMSTransporter").as_posix() + " -m verify 
   ...: -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password
   ...: -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"

In [7]: shlex.split(command)[0]
Out[7]: 'C:/progra~2/itms/iTMSTransporter'

Като алтернатива, следното – подобрена версия на [4] – е нещо, което трябва да работи и на двете операционни системи. В този случай posix се определя чрез os.name. Това също разчита на използването на pathlib за форматиране на пътя, съобразен с ОС.

In [8]: import os

In [9]: command = str(Path(r"C:\progra~2\itms\iTMSTransporter")) + " -m verify 
   ...: -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password
   ...: -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"

In [10]: shlex.split(command, posix=(os.name == "posiX"))[0]
Out[10]: 'C:\\progra~2\\itms\\iTMSTransporter'
person lcnittl    schedule 22.08.2020