Łączenie ścieżek niezależnych od platformy przy użyciu „/”, „\”?

86

W Pythonie mam zmienne base_diri filename. Chciałbym je połączyć, aby uzyskać fullpath. Ale pod Windows powinienem używać \i dla POSIX /.

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

Jak mogę uczynić tę platformę niezależną?

Jakub M.
źródło

Odpowiedzi:

150

Chcesz użyć do tego os.path.join () .

Zaletą używania tego zamiast łączenia ciągów itp. Jest świadomość różnych problemów specyficznych dla systemu operacyjnego, takich jak separatory ścieżek. Przykłady:

import os

W systemie Windows 7 :

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

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

W systemie Linux :

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

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

Os moduł zawiera wiele użytecznych metod manipulacji ścieżkę katalogu, a znalezienie się informacje dotyczące konkretnego systemu operacyjnego, takich jak separator używany w ścieżkach poprzez os.sep

Levon
źródło
26

Zastosowanie os.path.join():

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

Os.path moduł zawiera wszystkie metody powinny potrzebnych dla platformy niezależnej manipulacji ścieżki, ale w przypadku trzeba wiedzieć, co jest separator ścieżki na bieżącej platformie można wykorzystać os.sep.

Andrew Clark
źródło
1
nie jest to pełna ścieżka, jeśli base_dirjest to ścieżka względna (pomimo że OP jej używa)
jfs
1
Dodanie abspath()wywołania powinno nadać mu pełną ścieżkę, jeśli jest w niej coś względnego.
martineau
@Andrew Clark, os.sep zwraca „\\” w systemie Windows, ale nadal działa, nawet jeśli używam „/”. Czy jest jakiś problem, jeśli użyjemy tylko „/”?
multigoodverse
12

Wykopując tutaj stare pytanie, ale w Pythonie 3.4+ możesz użyć operatorów pathlib :

from pathlib import Path

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

Jest potencjalnie bardziej czytelny, niż os.path.join()gdybyś miał tyle szczęścia, że ​​używa najnowszej wersji Pythona. Jeśli jednak musisz uruchomić kod w, powiedzmy, środowisku sztywnym lub starszym, rezygnujesz również z kompatybilności ze starszymi wersjami Pythona.

Toby
źródło
Bardzo lubię pathlib. Jednak często nie jest instalowany domyślnie w instalacjach Python2. Jeśli nie chcesz, aby użytkownicy również musieli instalować pathlib, os.path.join()jest to prostsza droga.
Marcel Waldvogel
7
import os
path = os.path.join("foo", "bar")
path = os.path.join("foo", "bar", "alice", "bob") # More than 2 params allowed.
varunl
źródło
1

Zrobiłem dla tego klasę pomocniczą:

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

Zastosowanie to:

    a = u("http://some/path")
    b = a + "and/some/another/path" # http://some/path/and/some/another/path
sashab
źródło
Czy to nie spowoduje wstawienia odwrotnych ukośników w systemie Windows?
Marcel Waldvogel
0

Dzięki za to. Dla każdego, kto widzi to przy użyciu fbs lub pyinstaller i zamrożonych aplikacji.

Mogę skorzystać z poniższego, który teraz działa idealnie.

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

Robiłem tę głupotę, która wcześniej oczywiście nie była idealna.

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
źródło