Відкрийте файл у відносному місці в Python


132

Припустимо, код 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); безглуздо
Russ

3
І для гарної заходи ... 5) використання контексту охоронців , щоб тримати його в чистоті і не забути закрити файл: with open(path, 'r+') as fp:. Дивіться тут найкращі пояснення withтверджень, які я бачив.
Russ

поряд із необхідним доглядом за косою рисою, як тільки було зазначено, є функція os.path.abspathшвидкого відкриття повного шляху відносного шляху. остаточна заява виглядає приблизно так:os.path.abspath('./2091/sample.txt')
OPMendeavor

Відповіді:


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)

Я виявив, що нижче простий код буде працювати .. чи є у нього недоліки? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + файл fp = open (шлях, 'r +'); <code>

@Arash Недоліком цього є cwd (поточний робочий каталог) може бути що завгодно, і не обов'язково буде там, де знаходиться ваш сценарій.
Cory Mawhorter

5
__file__це відносний шлях (принаймні, з моєї установки, чомусь), і вам потрібно зателефонувати os.path.abspath(__file__)спочатку. osx / homebrew 2.7
Cory Mawhorter

2
os.path.dirname ( файл ) не працює для мене в Python 2.7. Це показNameError: name '__file__' is not defined
Сумендра

1
@Soumendra Я думаю, ви пробуєте це в консолі. Спробуйте його у файлі * .py.
Енку

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)

Це чудова відповідь, оскільки він намагається динамічно створювати абсолютний шлях до системи до потрібного файлу.

Cory Mawhorter зауважив, що __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модуль все ще має деякі корисні функції.


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?
foobarbecue

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 OS це, але успіху у мене не було.
Венло Полотто

Цікаво - ви можете надрукувати 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)

Замість path = "/".join(script_directory) + "/" + rel_pathвас слід використовувати os модуль, як в path = os.path.join(script_directory, rel_path). Замість того, щоб вручну script_path = os.path.dirname(__file__)
проаналізувати

3

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


3

Спробуйте це:

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. Це працює для мене!


2

Не впевнений, чи працює це скрізь.

Я використовую ipython в ubuntu.

Якщо ви хочете прочитати файл у підкаталозі поточної папки:

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

ваш сценарій знаходиться в поточній папці, просто спробуйте це:

import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)

1

Python просто передає ім'я файлу, яке ви даєте йому операційній системі, яка відкриває його. Якщо ваша операційна система підтримує відносні шляхи на зразок main/2091/data.txt(натяк: це так), то це буде добре.

Ви можете виявити, що найпростіший спосіб відповісти на таке питання - спробувати його і подивитися, що відбувається.


2
Неправда ... робочий каталог всередині сценарію - це місце, з якого ви запустили скрипт, а не розташування сценарію. Якщо ви запустите скрипт з іншого місця (можливо, сценарій знаходиться у вашому системному шляху), відносний шлях до підкаталогу не працюватиме. Будь ласка, дивіться мою відповідь про те, як обійти це.
Russ

@Russ - приклад ОП 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.")

0

Коли я був початківцем, я знайшов ці описи трохи залякаючими. Як спочатку я б спробував For Windows

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

і це підняло б syntax error. Я звик багато плутати. Потім після деякого серфінгу через Google. з'ясував, чому сталася помилка. Пишуть це для початківців

Це тому, що для зчитування шляху в Unicode ви просто додаєте a \при запуску шляху до файлу

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

І тепер він працює лише додати \перед запуском каталогу.


1
Підсумки - це символи втечі для кількох символів. Якщо у вас трапляється, \tнаприклад \top\directory, "\ t" трактується як символ табуляції, і ваш трюк не вдається. Найкращим варіантом є використання необробленого формату рядка, r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'який не намагається "уникнути" символів.
Рональд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.