Относительные пути в Python


Я создаю простой вспомогательный скрипт для работы, который скопирует пару файлов шаблонов в нашей базе кода в текущий каталог. Однако у меня нет абсолютного пути к каталогу, в котором хранятся шаблоны. У меня есть относительный путь от скрипта, но когда я вызываю скрипт, он рассматривает его как путь относительно текущего рабочего каталога. Есть ли способ указать, что этот относительный url-адрес находится в местоположении скрипта?

12 161

12 ответов:

в файле, который имеет скрипт, вы хотите сделать что-то вроде этого:

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

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

обновление: я отвечаю на комментарий здесь, чтобы я мог вставить пример кода. : -)

правильно ли я думаю, что __file__ не всегда доступен (например, когда вы запускаете файл напрямую, а не импортируете его)?

Я предполагаю, что вы имеете в виду __main__ скрипт при упоминании запуска файла напрямую. Если это так, то это не похоже на мою систему (python 2.5.1 на OS X 10.5.7):

#foo.py
import os
print os.getcwd()
print __file__

#in the interactive interpreter
>>> import foo
/Users/jason
foo.py

#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py

однако, я знаю, что есть некоторые причуды с __file__ на C-расширения. Например, я могу сделать это на моем Mac:

>>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'

однако, это вызывает исключение на моих окнах машина.

вам нужно os.path.realpath (пример ниже добавляет в родительский каталог к вашему пути)

import sys,os
sys.path.append(os.path.realpath('..'))

Как указано в принятой ответ

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')

Я просто хочу добавить, что

последняя строка не может начинаться с обратной косой черты, не влияет на строку должен включать обратную косую черту

Это должно быть что-то вроде

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, 'relative','path','to','file','you','want')

принятый ответ может ввести в заблуждение в некоторых случаях , пожалуйста, обратитесь к этой ссылка на описание

рассмотреть мой код:

import os


def readFile(filename):
    filehandle = open(filename)
    print filehandle.read()
    filehandle.close()



fileDir = os.path.dirname(os.path.realpath('__file__'))
print fileDir

#For accessing the file in the same folder
filename = "same.txt"
readFile(filename)

#For accessing the file in a folder contained in the current folder
filename = os.path.join(fileDir, 'Folder1.1/same.txt')
readFile(filename)

#For accessing the file in the parent folder of the current folder
filename = os.path.join(fileDir, '../same.txt')
readFile(filename)

#For accessing the file inside a sibling folder.
filename = os.path.join(fileDir, '../Folder2/same.txt')
filename = os.path.abspath(os.path.realpath(filename))
print filename
readFile(filename)

посмотреть sys.путь Как инициализируется при запуске программы, Первый элемент этого списка, path[0], является каталогом, содержащим скрипт, который был использован для вызова интерпретатора Python.

используйте этот путь в качестве корневой папки, из которой вы применить относительный путь

>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\Python25\Lib\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\Python25\Lib\idlelib\path_to_libs'

вместо

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

как и в принятом ответе, было бы более надежным использовать:

import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

потому что использование _ _ file__ вернет файл, из которого был загружен модуль, если он был загружен из файла, поэтому если файл со скриптом вызывается из другого места, возвращенный каталог не будет правильным.

эти ответы дают более подробную информацию:https://stackoverflow.com/a/31867043/5542253 и https://stackoverflow.com/a/50502/5542253

этот код вернет абсолютный путь к основному скрипту.

import os
def whereAmI():
    return os.path.dirname(os.path.realpath(__import__("__main__").__file__))

Это будет работать даже в модуле.

сейчас 2018 год, и Python уже развился до __future__ давным-давно. Так как насчет использования удивительного pathlib приходя с Python 3.4, чтобы выполнить задачу, а не бороться с os,os.path,glob,shutil и т. д.

Итак, у нас есть 3 варианта (возможно, дублированная):

  • mod_path: который является путем простой вспомогательный скрипт
  • src_path: который содержит пару из файлов шаблонов ждут, чтобы быть скопированы.
  • cwd:текущей директории, назначение этих файлов шаблонов.

и проблема заключается в следующем:у нас нет полный путь src_path, только это относительный путь до mod_path.

теперь давайте решим это с удивительным pathlib:

# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

в будущем, это так просто. :Д


кроме того, мы можем выбрать и проверить и скопировать/переместить эти файлы шаблонов с pathlib:

if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)

привет в первую очередь вы должны понимать функции ОС.путь.abspath(путь) и ОС.путь.relpath(путь)

короче ОС.путь.abspath(путь) делает относительный путь до абсолютный путь. И если путь является абсолютным путем, то функция возвращает тот же самый путь.

аналогично ОС.путь.relpath(путь) делает абсолютный путь до относительная путь. И если предоставленный путь сам является относительным путем, то функция возвращает тот же путь.

ниже пример может позволить вам понять выше понятие правильно:

предположим у меня есть файл input_file_list.txt который содержит список входных файлов для обработки моим python скрипт.

D:\conc\input1.dic

D:\conc\input2.dic

D:\Copyioconc\input_file_list.txt

Если вы видите выше структуру папок, input_file_list.txt присутствует Copyofconc папка и файлы, которые будут обрабатываться скриптом python, присутствуют в conc папку

но содержимое файла input_file_list.txt как показано ниже:

..\\конц вход1.dic

..\conc\input2.dic

и мой скрипт python присутствует в D: диск.

и относительный путь, указанный в input_file_list.txt файл относительно пути input_file_list.txt.

поэтому, когда скрипт python должен выполнить текущий рабочий каталог (используйте ОС.getcwd () получить путь)

Как мой относительный путь относительно input_file_list.txt, что составляет "D:\Copyofconc", Я должен изменить текущий рабочий каталог "D:\Copyofconc".

поэтому я должен использовать ОС.оператор chdir('D:\Copyofconc'), Так что текущий рабочий каталог должен быть "D:\Copyofconc".

теперь, чтобы получить файлы input1.dic и input2.dic, Я буду читать строки "..\\конц вход1.dic " затем должен использовать команду

input1_path= os.путь.abspath('..\\конц вход1.dic') (чтобы изменить относительный путь на абсолютный путь. Вот как выглядит текущий рабочий каталог "D:\Copyofconc", файл".\\конц вход1.dic " должен быть доступен относительно "D:\Copyofconc")

Так input1_path должно быть "D:\conc\input1.Дик"

альтернатива, которая работает для меня:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))

то, что сработало для меня, использует sys.path.insert. Затем я указал каталог, который мне нужно было пойти. Например, мне просто нужно было подняться на один каталог.

import sys
sys.path.insert(0, '../')

Я не уверен, что это относится к некоторым из более старых версий, но я считаю, что Python 3.3 имеет собственную поддержку относительного пути.

например, следующий код должен создать текстовый файл в той же папке, что и скрипт Python:

open("text_file_name.txt", "w+t")

(обратите внимание, что в начале не должно быть прямой или обратной косой черты, если это относительный путь)