Kiedyś otwierałem pliki, które znajdowały się w tym samym katalogu, co aktualnie uruchomiony skrypt Pythona, po prostu używając polecenia takiego jak
open("Some file.txt", "r")
Jednak odkryłem, że gdy skrypt był uruchamiany w systemie Windows przez dwukrotne kliknięcie, próbował otworzyć plik z niewłaściwego katalogu.
Od tego czasu używam polecenia formularza
open(os.path.join(sys.path[0], "Some file.txt"), "r")
kiedykolwiek chciałem otworzyć plik. Działa to dla mojego konkretnego zastosowania, ale nie jestem pewien, czy sys.path[0]
może się nie powieść w innym przypadku użycia.
Więc moje pytanie brzmi: jaki jest najlepszy i najbardziej niezawodny sposób na otwarcie pliku, który znajduje się w tym samym katalogu, co aktualnie uruchomiony skrypt Pythona?
Oto, co udało mi się do tej pory ustalić:
os.getcwd()
ios.path.abspath('')
zwraca „bieżący katalog roboczy”, a nie katalog skryptów.os.path.dirname(sys.argv[0])
ios.path.dirname(__file__)
zwróć ścieżkę używaną do wywołania skryptu, która może być względna lub nawet pusta (jeśli skrypt znajduje się w cwd). Ponadto__file__
nie istnieje, gdy skrypt jest uruchamiany w środowisku IDLE lub PythonWin.sys.path[0]
ios.path.abspath(os.path.dirname(sys.argv[0]))
wydaje się zwracać katalog skryptów. Nie jestem pewien, czy jest jakaś różnica między tymi dwoma.
Edytować:
Właśnie zdałem sobie sprawę, że to, co chcę zrobić, lepiej byłoby opisać jako „otwórz plik w tym samym katalogu, co zawierający moduł”. Innymi słowy, jeśli importuję moduł, który napisałem, który znajduje się w innym katalogu i ten moduł otwiera plik, chcę, aby szukał pliku w katalogu modułu. Nie sądzę, aby cokolwiek, co znalazłem, było w stanie to zrobić ...
__file__
nie można użyć, użyjsys.argv[0]
zamiastdirname(__file__)
. Reszta powinna działać zgodnie z oczekiwaniami. Lubię używać,__file__
ponieważ w kodzie bibliotekisys.argv[0]
może w ogóle nie wskazywać na twój kod, szczególnie jeśli jest importowany za pomocą skryptu innej firmy.realpath( join( getcwd(), dirname(__file__) ))
opisanego tutaj?Cytat z dokumentacji Pythona:
sys.path [0] jest tym, czego szukasz.
źródło
os.path.join(sys.path[0], 'some file.txt')
. Powinno to poprawnie obsługiwać spacje i ukośniki we wszystkich systemach.Ok, oto co robię
sys.argv jest zawsze tym, co wpisujesz w terminalu lub używasz jako ścieżki do pliku podczas wykonywania go za pomocą python.exe lub pythonw.exe
Na przykład możesz uruchomić plik text.py na kilka sposobów, każdy z nich daje inną odpowiedź, zawsze podają ścieżkę, w której wpisano python.
Ok, więc wiedz, że możesz uzyskać nazwę pliku, wielka sprawa, teraz, aby uzyskać katalog aplikacji, który możesz znać, użyj os.path, w szczególności abspath i dirname
To da to:
zawsze wyświetli to bez względu na to, czy wpiszesz python test.py czy python "C: \ Documents and Settings \ Admin \ test.py"
Problem z używaniem __file__ Rozważ te dwa pliki test.py
import_test.py
Wyjście „python test.py”
Wynik „python test_import.py”
Jak widzisz, plik zawsze podaje plik Pythona, z którego jest uruchamiany, gdzie jako sys.argv [0] zawsze podaje plik, który uruchomiłeś z interpretera. W zależności od potrzeb będziesz musiał wybrać, który z nich najlepiej odpowiada Twoim potrzebom.
źródło
__file__
jest niby do „zawsze daje ścieżkę do bieżącego pliku” isys.argv[0]
jest niby do „zawsze podać ścieżkę do skryptu, który zainicjował proces”. W każdym razie użycie__file__
w wywołanym skrypcie zawsze daje dokładne wyniki.__file__
na najwyższym poziomie skryptu, będzie działać zgodnie z oczekiwaniami.Udało mi się pomyślnie użyć kodu dostarczonego przez dcolish, ponieważ miałem podobny problem z odczytem określonego pliku tekstowego. Plik nie znajduje się w tym samym cwd co plik Pythona.
źródło
Zrobiłbym to w ten sposób:
Powyższy kod buduje bezwzględną ścieżkę do pliku przy użyciu abspath i jest równoważny użyciu
normpath(join(os.getcwd(), path))
[pochodzi z pydoc]. Następnie sprawdza, czy ten plik faktycznie istnieje, a następnie używa menedżera kontekstu, aby go otworzyć, więc nie musisz pamiętać o wywołaniu close na uchwycie pliku. IMHO, robienie tego w ten sposób na dłuższą metę zaoszczędzi ci wiele bólu.źródło
os.path.abspath
nie rozwiązuje ścieżek do plików w tym samym folderze co skrypt, jeśli skrypt nie znajduje się w bieżącym katalogu.