Открыть файл в относительном месте в Python

133

Предположим, что код python выполняется в неизвестном ранее каталоге Windows, например, «main», и где бы ни был установлен код при его запуске, ему необходимо получить доступ к каталогу «main / 2091 / data.txt».

как мне использовать функцию open (location)? какая должна быть локация?

Редактировать :

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

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');
камелия
источник
1
Вы используете обратную косую черту без экранирования. Это один из недостатков.
orip
6
Несколько недостатков. 1) Согласно @orip, используйте косую черту для путей, даже в окнах. Ваша строка не будет работать. Или используйте необработанные строки, например r"\2091\sample.txt". Или уйти от них вроде "\\2091\\sample.txt"(но это раздражает). Кроме того, 2) вы используете getcwd (), который является путем, по которому вы были при выполнении скрипта. Я думал, что вы хотели относительно местоположения сценария (но теперь мне интересно). И 3) всегда используйте os.pathфункции для управления путями. Линия соединения вашего пути должна быть os.path.join(os.getcwd(), file)4); бессмысленно
Расс
3
И для хорошей меры ... 5) использование контекста охранников , чтобы держать его в чистоте и не забыть закрыть файл: with open(path, 'r+') as fp:. Смотрите здесь лучшее объяснение withутверждений, которые я видел.
Russ
Помимо необходимой осторожности с косой чертой, как только что указывалось, есть функция, os.path.abspathпозволяющая легко получить полный путь относительного пути, который нужно открыть. последнее утверждение выглядит так:os.path.abspath('./2091/sample.txt')
OPMendeavour

Ответы:

189

При работе с такими вещами вам нужно быть осторожным с вашим фактическим рабочим каталогом. Например, вы не можете запускать сценарий из каталога, в котором находится файл. В этом случае вы не можете просто использовать относительный путь сам по себе.

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

Итак, вы можете возиться с чем-то вроде этого:

import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)
Russ
источник
Я обнаружил, что приведенный ниже простой код будет работать .. есть ли у него недостатки? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>
@Arash Недостатком этого является то, что cwd (текущий рабочий каталог) может быть любым, и не обязательно там, где находится ваш скрипт.
Кори Мохортер
5
__file__- это относительный путь (по крайней мере, в моей настройке, по какой-то причине), и os.path.abspath(__file__)сначала вам нужно позвонить . osx / homebrew 2.7
Кори Мохортер
2
os.path.dirname ( file ) у меня не работает в Python 2.7. Это показываетNameError: name '__file__' is not defined
Soumendra
1
@Soumendra Я думаю, вы пробуете это в консоли. Попробуйте в файле * .py.
Enku
35

Этот код отлично работает:

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)
Фахад Халим
источник
Для меня доступ к файлу в родительской папке текущей папки не сработал .. .. добавляется в виде строки ..
М. Пол
Не работает в Windows. Путь к файлу правильный, но Python указывает «файл не найден» и показывает путь с разделителями \\.
lonstar
26

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

Для справки, его первоначальный ответ был:

import os
script_dir = os.path.dirname(__file__)
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

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

Кори Мохортер заметил, что __file__это относительный путь (он тоже есть в моей системе), и предложил использовать os.path.abspath(__file__). os.path.abspathоднако возвращает абсолютный путь к вашему текущему скрипту (т.е. /path/to/dir/foobar.py)

Чтобы использовать этот метод (и то, как я в итоге заставил его работать), вам нужно удалить имя сценария в конце пути:

import os
script_path = os.path.abspath(__file__) # i.e. /path/to/dir/foobar.py
script_dir = os.path.split(script_path)[0] #i.e. /path/to/dir/
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

Результирующий abs_file_path (в этом примере) становится: /path/to/dir/2091/data.txt

Грант Хулегаард
источник
14
Вы даже можете комбинировать оба подхода для более простогоos.path.dirname(os.path.abspath(__file__))
Люк Тейлор
1
@LukeTaylor Действительно, это было бы лучше, чем пытаться воспроизвести os.path.dirnameфункциональность самостоятельно, как я сделал в своем ответе в прошлом году.
Грант Хулегард,
19

Это зависит от того, какую операционную систему вы используете. Если вам нужно решение, совместимое как с Windows, так и с * nix, например:

from os import path

file_path = path.relpath("2091/data.txt")
with open(file_path) as f:
    <do stuff>

должно работать нормально.

pathМодуль способен форматировать путь для любой операционной системы , он работает на. Кроме того, python отлично обрабатывает относительные пути, если у вас есть правильные разрешения.

Редактировать :

Как упоминалось kindall в комментариях, python в любом случае может преобразовывать пути в стиле unix и стиле Windows, поэтому будет работать даже более простой код:

with open("2091/data/txt") as f:
    <do stuff>

При этом у pathмодуля все еще есть некоторые полезные функции.

Wilduck
источник
3
relpath()преобразует путь в относительный путь. Поскольку это уже относительный путь, он ничего не сделает.
kindall
При необходимости он преобразует его из пути в стиле unix в путь в стиле Windows. Есть ли в os.pathмодуле другая функция, которая была бы лучшим выбором?
Wilduck
1
Windows уже будет нормально работать с путем в стиле UNIX. По крайней мере, будет серия на базе NT (2000, XP, Vista, 7). Никакого преобразования не требуется.
kindall
7
Этот ответ не совсем правильный и вызовет проблемы. Относительные пути по умолчанию относятся к текущему рабочему каталогу (путь, из которого был выполнен сценарий), а НЕ фактическое расположение сценария. Вам нужно использовать __file__. Пожалуйста, посмотрите мой ответ.
Russ
Автор этого ответа перепутал os.path.relpath с os.path.abspath?
foobar барбекю
15

Я трачу много времени на то, чтобы выяснить, почему мой код не может найти мой файл, работающий на Python 3, в системе Windows. Я добавил. до / и все работало нормально:

import os

script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, './output03.txt')
print(file_path)
fptr = open(file_path, 'w')
Анджело Полотто
источник
Лучше:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D
Я пробовал это на ОС Windows, но безуспешно.
Анджело Полотто
Интересно - можно ли напечатать script_dir? Затем переключите его на абсолютный путь, как вscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D
Я попробую, если получится, изменю ответ.
Анджело Полотто
6

Код:

import os
script_path = os.path.abspath(__file__) 
path_list = script_path.split(os.sep)
script_directory = path_list[0:len(path_list)-1]
rel_path = "main/2091/data.txt"
path = "/".join(script_directory) + "/" + rel_path

Объяснение:

Библиотека импорта:

import os

Используйте __file__для получения пути к текущему скрипту:

script_path = os.path.abspath(__file__)

Разделяет путь скрипта на несколько элементов:

path_list = script_path.split(os.sep)

Удалите последний элемент в списке (фактический файл сценария):

script_directory = path_list[0:len(path_list)-1]

Добавьте относительный путь к файлу:

rel_path = "main/2091/data.txt

Присоединитесь к элементам списка и добавьте файл относительного пути:

path = "/".join(script_directory) + "/" + rel_path

Теперь вы можете делать с файлом все, что хотите, например:

file = open(path)
Patriots299
источник
Вместо этого path = "/".join(script_directory) + "/" + rel_pathвы должны использовать модуль os, как в path = os.path.join(script_directory, rel_path). Вместо ручного анализа пути, который вы должны использоватьscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D
4

Попробуй это:

from pathlib import Path

data_folder = Path("/relative/path")
file_to_open = data_folder / "file.pdf"

f = open(file_to_open)

print(f.read())

Python 3.4 представил новую стандартную библиотеку для работы с файлами и путями, называемую pathlib. Меня устраивает!

dcampos
источник
3

Если файл находится в родительской папке, например. follower.txt, вы можете просто использоватьopen('../follower.txt', 'r').read()

Оливия Ляо
источник
2

Не уверен, работает ли это везде.

Я использую ipython в ubuntu.

Если вы хотите прочитать файл в подкаталоге текущей папки:

/current-folder/sub-directory/data.csv

ваш скрипт находится в текущей папке, просто попробуйте это:

import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)
Survi
источник
1

Python просто передает имя файла, которое вы ему даете, операционной системе, которая его открывает. Если ваша операционная система поддерживает относительные пути, такие как main/2091/data.txt(подсказка: поддерживает), тогда это будет работать нормально.

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

Kindall
источник
2
Неправда ... рабочий каталог внутри сценария - это место, откуда вы запустили сценарий, а не расположение сценария. Если вы запустите сценарий из другого места (возможно, сценарий находится на вашем системном пути), относительный путь к подкаталогу не будет работать. Пожалуйста, посмотрите мой ответ о том, как это обойти.
Russ
@Russ - пример OP использует getcwd(). Я читаю исходное описание как «относительно того, где я запускаю сценарий, независимо от того, где находится код».
orip
@orip - ОП добавил вызов getcwd () через 3 часа после вопроса. Неважно ... двигаться дальше. :)
Russ
1
import os
def file_path(relative_path):
    dir = os.path.dirname(os.path.abspath(__file__))
    split_path = relative_path.split("/")
    new_path = os.path.join(dir, *split_path)
    return new_path

with open(file_path("2091/data.txt"), "w") as f:
    f.write("Powerful you have become.")
Webucator
источник
0

Когда я был новичком, эти описания меня пугали. Как сначала я бы попробовал For Windows

f= open('C:\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f) 

и это поднимет syntax error. Я очень запутался. Затем, после некоторого серфинга в Google. выяснил, почему произошла ошибка. Написание этого для начинающих

Это потому, что для чтения пути в Unicode вы просто добавляете \путь к файлу при запуске

f= open('C:\\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f)

И теперь работает просто добавить \перед запуском каталог.

Chidhvilas
источник
1
Обратные косые черты - это escape-символы для нескольких символов. Если вы, \tнапример \top\directory, столкнулись с подобным , то '\ t' интерпретируется как символ табуляции, и ваш 'трюк' не срабатывает. Лучшим вариантом является использование формата необработанной строки, r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'который не пытается «экранировать» символы.
Рональд