Конкатенация путей независимо от платформы с использованием символов «/», «\»?

85

В python у меня есть переменные base_dirи filename. Я хотел бы их объединить, чтобы получить fullpath. Но под windows мне надо использовать \и для POSIX /.

fullpath = "%s/%s" % ( base_dir, filename ) # for Linux

Как я могу сделать эту платформу независимой?

Якуб М.
источник

Ответы:

149

Для этого вы хотите использовать os.path.join () .

Преимущество использования этого, а не конкатенации строк и т. Д., Заключается в том, что он знает о различных проблемах ОС, таких как разделители путей. Примеры:

import os

Под Windows 7 :

base_dir = r'c:\bla\bing'
filename = r'data.txt'

os.path.join(base_dir, filename)
'c:\\bla\\bing\\data.txt'

Под Linux :

base_dir = '/bla/bing'
filename = 'data.txt'

os.path.join(base_dir, filename)
'/bla/bing/data.txt'

Модуль os содержит множество полезных методов для управления каталогами, путями и поиска информации, специфичной для ОС, например, разделитель, используемый в путях через os.sep.

Левон
источник
26

Использование os.path.join():

import os
fullpath = os.path.join(base_dir, filename)

Модуль os.path содержит все методы, которые вам могут понадобиться для независимой от платформы манипуляции с путями, но в случае, если вам нужно знать, какой разделитель путей находится на текущей платформе, вы можете использовать os.sep.

Эндрю Кларк
источник
1
это не полный путь, если base_dirэто относительный путь (несмотря на то, что OP его использует)
jfs
1
Добавление abspath()вызова должно сделать его полным путем, если в нем есть что-то относительное.
Мартино
@ Эндрю Кларк, os.sep возвращает "\\" в Windows, но он все равно работает, даже если я использую "/". Есть ли проблема, если мы просто используем "/"?
multigoodverse
12

Копаем здесь старый вопрос, но в Python 3.4+ вы можете использовать операторы pathlib :

from pathlib import Path

# evaluates to ./src/cool-code/coolest-code.py on Mac
concatenated_path = Path("./src") / "cool-code\\coolest-code.py"

Это потенциально более читабельно, чем os.path.join()если бы вам посчастливилось использовать последнюю версию Python. Но вы также жертвуете совместимостью со старыми версиями Python, если вам нужно запускать код, скажем, в жесткой или устаревшей среде.

Тоби
источник
Очень люблю pathlib. Однако он часто не устанавливается по умолчанию в установках Python2. Если вы не хотите, чтобы пользователи также устанавливали pathlib, os.path.join()это более простой способ.
Марсель Вальдфогель
7
import os
path = os.path.join("foo", "bar")
path = os.path.join("foo", "bar", "alice", "bob") # More than 2 params allowed.
Варунл
источник
1

Я сделал для этого вспомогательный класс:

import os

class u(str):
    """
        Class to deal with urls concat.
    """
    def __init__(self, url):
        self.url = str(url)

    def __add__(self, other):
        if isinstance(other, u):
            return u(os.path.join(self.url, other.url))
        else:
            return u(os.path.join(self.url, other))

    def __unicode__(self):
        return self.url

    def __repr__(self):
        return self.url

Использование:

    a = u("http://some/path")
    b = a + "and/some/another/path" # http://some/path/and/some/another/path
сашаб
источник
Это не приведет к вставке обратной косой черты в Windows?
Марсель Вальдфогель
0

Спасибо за это. Для всех, кто видит это, используя fbs или pyinstaller и замороженные приложения.

Я могу использовать нижеприведенное, которое теперь отлично работает.

target_db = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), "sqlite_example.db")

Я делал это беготня, до этого явно не идеально.

if platform == 'Windows':
    target_db = (os.path.abspath(os.path.dirname(sys.argv[0])) + "\\" + "sqlite_example.db")

if platform == 'Linux' or 'MAC':
    target_db = (os.path.abspath(os.path.dirname(sys.argv[0])) + "/" + "sqlite_example.db")

target_db_path = target_db
print(target_db_path)
Mik R
источник