os.path.join - могу ли я получить согласованность между Windows и Cygwin? - PullRequest
5 голосов
/ 12 мая 2011

Мне бы очень хотелось, чтобы набор компонентов имени файла дал мне непротиворечивые и «красивые» имена файлов как в Windows, так и в Cygwin.Вот что я попробовал:

  Input                                Windows      Cygwin
1 os.path.join('c:', 'foo', 'bar')     c:foo\bar    c:/foo/bar
2 os.path.join('c:\\', 'foo', 'bar')   c:\foo\bar   c:\/foo/bar
3 os.path.join('c:/', 'foo', 'bar')    c:/foo\bar   c:/foo/bar

1 - это не то, что мне нужно в Windows, мне нужен абсолютный путь, не относящийся к текущему каталогу.

2 и 3 обаработают, но не являются (я настоящим определяю) «красивыми», так как они смешивают прямую и обратную косую черту на одной или другой платформе.Мои сообщения об ошибках и журналах будут более читабельными, если я смогу избежать этого.

Вариант 4 - определить для себя переменную driveroot, равную c:\ в Windows и /cygdrive/c в Cygwin.Или функция, принимающая букву диска и возвращающая то же самое.Но я бы также предпочел бы избегать особых случаев для каждой платформы между этими двумя.

Могу ли я иметь все, что хочу (объединить идентичные компоненты пути, чтобы получить результат, относящийся к одному и тому жеабсолютный путь на обеих платформах, и не смешивает разделители пути на любой платформе)?Или я должен где-то пойти на компромисс?

[Редактировать: в случае, если это помогает, основной вариант использования состоит в том, что c:\foo - это путь, о котором я знаю во время конфигурации, тогда как bar (и другие компоненты) рассчитываются позже.Таким образом, мой настоящий код в настоящее время выглядит примерно так:

dir = os.path.join('c:\\', 'foo')

# some time later

os.path.join(dir, 'bar')

Используется вариант 2, который приводит к «приятному» сообщению о именах файлов в Windows, но «не очень» к отчетам о файлах в Cygwin.Чего я хочу избежать, если это возможно, так это:

if this_is_cygwin():
    dir = '/cygdrive/c/foo'
else:
    dir = 'c:\\foo'

]

Ответы [ 2 ]

4 голосов
/ 12 мая 2011

Редактировать: Дэвид указал, что мое понимание «текущего каталога» в Windows неверно.Сожалею.Однако попробуйте использовать os.path.abspath, чтобы получить красивые симпатичные пути, или os.path.normpath, если вам не нужны абсолютные пути.

В методе 1

os.path.join('c:', 'foo', 'bar')

Выходные данные, c:foo\bar, верно.Это означает, что путь foo\bar ниже текущего каталога на c:, который отличается от корневого каталога.os.path.join делает именно то, что вы ему говорите, то есть берете c: (каталог current на диске c) и добавляете к нему дополнительные биты.

В методе 2,

os.path.join(r'c:\', 'foo', 'bar')

Вывод для Cygwin правильный, потому что в Cygwin c:\ не является корнем диска.

То, что вам нужно, это функция os.abspath.Это даст вам абсолютную нормализованную версию пути, который вы ему дадите.

Однако: Вы не получите ту же строку в Cygwin и Windows.Надеюсь, вы этого не ищете.

0 голосов
/ 14 сентября 2013

На работе мне приходится иметь дело с довольно случайными комбинациями Windows без Cygiwn, Cygwin с не-Cygwin Python, Cygwin с Cygwin Python и Unix. Я не нашел способа справиться с этим, чем я особенно горжусь, но наименее ненавистный подход, который я нашел до сих пор, - это всегда использовать то, что Cygwin называет «смешанным стилем» пути в Windows. Это путь в стиле Windows, но с косой чертой вместо обратной. Например, c: /foo/bar.txt. Он также избегает многих ошибок, таких как оболочки Cygwin bash, которые видят «\» как побег. К сожалению, это означает, что вам не хватает многих встроенных в Python утилит для манипулирования путями и трудных действий.

У меня нет доступа к машине с Python и Cygwin на этом банкомате, поэтому я не могу проверить приведенные ниже фрагменты кода. Я прошу прощения за любые ошибки ...



    #Combine a path
    path = '/'.join([ 'c:', 'foo', 'bar'])

    #Split it back apart
    pieces = path.split('/')

Если сомневаетесь, попробуйте вызвать Cygwin's cygpath. В Cygwin появляется много странных крайних случаев, например, тот факт, что / cygdrive / d / == d: \ и все же /cygdrive/d/../../ == c: \ cygwin (или где бы то ни было Cygwin установлен). Также помните, что обратные слэши используются в качестве escape-символов в путях стиля Unix, таких как / cygdrive / c / Documents \ и \ Settings. Cygpath делает удивительную работу, заботясь об этом, и если он недоступен, то обычно безопасно предположить, что ваши странные крайние случаи не существуют. <pre></p> <pre><code>import sys import subprocess #Buncha code here ... #We got somepath from somewhere, and don't know what format it's in. try: somepath = subprocess.check_output(['cygpath', '-m', somepath]) except subprocess.CalledProcessError: #Cheap attempt at coping with the possibility that we're in Windows, but cygpath isn't available. if sys.platform.startswith('win32'): mypath = somepath.replace('\\', '/') else: mypath = somepath #Now we can assume somepath is using forward slashes for delimiters.

Некоторые команды Windows сбиваются с толку, если вы передаете им путь в стиле Windows, а некоторые команды Cygwin сбиваются с толку, если вы передаете путь Windows или смешанный стиль. Например, rsync может запутаться в «c: /foo/bar.txt», потому что похоже, что вы пытаетесь указать «/foo/bar.txt» на удаленном компьютере с именем «c». Когда вы вызываете одну из этих привередливых программ для Windows или Cygwin, используйте cygpath, чтобы сделать ее счастливой. Если вы вызываете привередливую программу для Windows, а cygpath недоступен, попробуйте подход «winpath = mypath.replace ('/', '\')" из гетто. Я думаю, что это может закончиться неудачей, если вы конвертируете путь в стиле Unix и у вас нет Cygwin, но, надеюсь, если у вас нет Cygwin, у вас нет путей в стиле Unix для Windows, чтобы начать с ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...