Я не могу заставить процесс правильно открыть каталог в Windows из-за косой черты

Мне нужно использовать subprocess.Popen, чтобы открыть окно проводника (только в Windows) с путем, но путь, который я использую, имеет косую черту, и это не работает, только открывает обобщенное окно проводника ПК. Если я вручную заменю их обратной косой чертой, все будет работать нормально, но мне нужно, чтобы это произошло для переменного пути.

Я пытался использовать os.path.dirname, чтобы «нормализовать» путь, но это тоже не работает. IOW, этот код дает мне только обобщенное окно проводника ПК:

myRoot = "D:/SomePath/Somefile"
subprocess.Popen(r'explorer /select, myRoot')

или даже:

myRoot = "D:/SomePath/Somefile"
subprocess.Popen(r'explorer /select, os.path.abspath(myRoot)')

но это работает:

myRoot = "D:\SomePath\Somefile"
subprocess.Popen(r'explorer /select, myRoot')

Я также пытался вручную заменить эти строки с косой чертой, но я не могу получить это, сколько бы способов я ни пробовал (поэтому, очевидно, что-то не так). Любые подсказки? (Мне это нужно ТОЛЬКО для работы в Windows, и я никак не могу заставить косую черту не входить, потому что я читаю из файла, созданного с помощью внешней программы).

Я ценю помощь, которую люди пытаются предоставить - позвольте мне попытаться прояснить это. Строка пути поступает из внешнего файла, который я не могу контролировать. Таким образом, это ВСЕГДА выглядит как пример с косой чертой, который НЕ работает с открытием подпроцесса проводника, как бы я ни пытался (включая примеры, приведенные ниже).

Однако, если я просто вручную укажу путь с обратной косой чертой, это сработает. Итак, мне нужно что-то, что преобразует путь с прямой косой чертой в путь с обратной косой чертой. И пока ничего из предложенного здесь не работает.


person Mike Kelley    schedule 03.05.2019    source источник
comment
Что вы имеете в виду, говоря, что я также пытался вручную заменить эти строки с косой чертой, но я не могу получить это, независимо от того, сколько способов я пробовал? В вашем третьем примере с обратной косой чертой вы говорите, что это работает.   -  person Niels Henkens    schedule 03.05.2019
comment
2 способ работает   -  person Smart Manoj    schedule 03.05.2019
comment
Нет, ни одна из этих замен не работает. Второй (с .replace) приводит меня в каталог «Мои документы» (странно, потому что путь находится на диске D:, поэтому C: там вообще нет). И то, что я говорю, когда никакие замены не работают, я имею в виду, что вычисленные замены не работают. Я могу вручную написать путь с правильными косыми чертами, но независимо от того, что я пытаюсь заменить эти косые черты программно, это не работает — он не заменит их и не вернет правильный путь.   -  person Mike Kelley    schedule 03.05.2019
comment
ХОРОШО!!!! УСПЕХ -- спасибо SmartManoj! ЭТО действительно работает (не совсем уверен, как сказать, что это ответ, когда он вроде как похоронен здесь, но я думаю, что использование фигурных скобок было ключом). Может быть, вы могли бы опубликовать это как ответ, который я мог бы затем проголосовать?   -  person Mike Kelley    schedule 03.05.2019


Ответы (2)


почти уверен, что это не имеет ничего общего с «косой чертой», но вызвано несколькими другими путаницами в том, как работает Python и как аргументы команды передаются от одного процесса к другому.

myRoot = "D:/SomePath/Somefile"
subprocess.Popen(rf'explorer /select, {os.path.abspath(myRoot)}')

работает, потому что переменная Python была расширена в строку, переданную в Popen, это эквивалентно:

cmdline = rf'explorer /select, {os.path.abspath(myRoot)}'
subprocess.Popen(cmdline)

что также эквивалентно:

cmdline = 'explorer /select, {root}'.format(
    root=os.path.abspath(myRoot))
subprocess.Popen(cmdline)

префикс f к строке известен как "f-string" (сокращенно для форматированных строковых литералов)

если вы print(cmdline), вы увидите, что он был расширен до: "explorer /select, D:/SomePath/Somefile" и, следовательно, путь может попасть в процесс MS Explorer.

когда вы запускали Popen(r'explorer /select, myRoot'), переменная myRoot не расширялась, и, следовательно, Explorer видел только текст "myRoot", который он, вероятно, игнорировал.

Рекомендуемой альтернативой будет передача list в Popen, где каждый элемент является отдельным аргументом командной строки. Например:

Popen(['explorer', '/select', myRoot])

что похоже на то, что вы пытались сделать, но не получилось правильно.

Другая проблема, с которой у вас, похоже, возникли проблемы, связана с «escape-последовательностями» и строками. Когда вы пишете код, обратная косая черта записывается как '\\', но это всего лишь один символ после его анализа. Например, с:

myRoot = "D:\\SomePath\\Somefile"
print(myRoot)

просто распечатает: D:\SomePath\Somefile. Эта переменная также должна нормально работать с приведенным выше вызовом Popen.

Префикс r отключает эту обработку экранирования и был разработан для «регулярных выражений» (или «регулярных выражений», см. re модуль Python). Есть много статей об этом, надеюсь, что-то из того, что я написал, содержит ключевые слова, понятные Google.

person Sam Mason    schedule 03.05.2019
comment
Спасибо, это многое объясняет (и привело меня туда, куда я хотел). Я проголосовал, но он говорит, что с менее чем 15 повторениями он не будет отображаться / учитываться, но у меня есть 15 повторений, поэтому я немного не понимаю, почему это не сработало). - person Mike Kelley; 04.05.2019

Используйте модуль pathlib.

from pathlib import Path
myRoot = Path("D:/path/to/wherever")

Это работает и с subprocess

person isaactfa    schedule 03.05.2019