เปิดไฟล์ในตำแหน่งสัมพัทธ์ใน Python


135

สมมติว่ารหัส python ถูกเรียกใช้โดยไม่รู้จักโดยไดเรกทอรี windows รุ่นก่อนพูดว่า 'main' และที่ใดก็ตามที่ติดตั้งรหัสเมื่อเรียกใช้จำเป็นต้องเข้าถึงไดเรกทอรี 'main / 2091 / data.txt'

ฉันจะใช้ฟังก์ชันเปิด (ตำแหน่ง) ได้อย่างไร ตำแหน่งที่ตั้งควรเป็นอย่างไร

แก้ไข:

ฉันพบว่าโค้ดด้านล่างใช้งานได้.. มันมีข้อเสียอะไรไหม?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');

1
คุณกำลังใช้แบ็กสแลชที่ไม่ใช้ค่า Escape นั่นเป็นข้อเสียอย่างหนึ่ง
orip

6
ข้อเสียหลายประการ 1) ตาม @orip ให้ใช้เครื่องหมายทับสำหรับพา ธ แม้กระทั่งบน windows สตริงของคุณใช้ไม่ได้ หรือใช้สตริงดิบเช่น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')
OPMendeavour

คำตอบ:


192

ด้วยสิ่งประเภทนี้คุณต้องระวังว่าไดเรกทอรีการทำงานจริงของคุณคืออะไร ตัวอย่างเช่นคุณไม่สามารถรันสคริปต์จากไดเร็กทอรีที่มีไฟล์อยู่ในกรณีนี้คุณไม่สามารถใช้พา ธ สัมพัทธ์ด้วยตัวมันเองได้

หากคุณแน่ใจว่าไฟล์ที่คุณต้องการอยู่ในไดเร็กทอรีย่อยที่อยู่ใต้ตำแหน่งที่แท้จริงของสคริปต์คุณสามารถใช้__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) + file fp = open (path, '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
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)

สำหรับฉันการเข้าถึงไฟล์ในโฟลเดอร์หลักของโฟลเดอร์ปัจจุบันไม่ได้ผล.. ถูกเพิ่มเป็นสตริง ..
M. Paul

ไม่ทำงานบน 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)

นี่เป็นคำตอบที่ยอดเยี่ยมเนื่องจากพยายามสร้างเส้นทางระบบสัมบูรณ์ไปยังไฟล์ที่ต้องการแบบไดนามิก

คอรี 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ฟังก์ชันด้วยตัวคุณเองเหมือนที่ฉันทำในคำตอบของฉันเมื่อปีที่แล้ว
Grant Hulegaard

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 สามารถแปลงระหว่างพา ธ สไตล์ยูนิกซ์และสไตล์วินโดวส์ได้ดังนั้นโค้ดที่ง่ายกว่าก็ใช้ได้:

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

ดังที่กล่าวไว้pathโมดูลยังคงมีฟังก์ชันที่มีประโยชน์บางอย่าง


3
relpath()แปลงชื่อพา ธ เป็นพา ธ สัมพัทธ์ เนื่องจากเป็นเส้นทางสัมพัทธ์อยู่แล้วจึงไม่ทำอะไรเลย
kindall

มันจะแปลงจากพา ธ สไตล์ยูนิกซ์ไปเป็นพา ธ สไตล์วินโดว์ตามความเหมาะสม มีฟังก์ชั่นอื่นใน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')

Better:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D

ฉันลองใช้ Windows OS แล้ว แต่ไม่ประสบความสำเร็จ
Ângelo Polotto

น่าสนใจ - คุณพิมพ์ script_dir ได้ไหม จากนั้นเปลี่ยนเป็นเส้นทางสัมบูรณ์ดังscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D

ฉันจะพยายามถ้าฉันทำสำเร็จฉันจะเปลี่ยนคำตอบ
Ângelo Polotto

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 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 ได้ผลสำหรับฉัน!


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)

1

Python เพียงแค่ส่งชื่อไฟล์ที่คุณให้ไปยังระบบปฏิบัติการซึ่งจะเปิดขึ้นมา หากระบบปฏิบัติการของคุณรองรับพา ธ สัมพัทธ์เช่นmain/2091/data.txt(hint: it does) ก็จะใช้ได้ดี

คุณอาจพบว่าวิธีที่ง่ายที่สุดในการตอบคำถามเช่นนี้คือลองดูว่าเกิดอะไรขึ้น


2
ไม่เป็นความจริง ... ไดเร็กทอรีการทำงานภายในสคริปต์คือตำแหน่งที่คุณเรียกใช้สคริปต์ไม่ใช่ตำแหน่งของสคริปต์ หากคุณรันสคริปต์จากที่อื่น (บางทีสคริปต์อาจอยู่ในเส้นทางระบบของคุณ) พา ธ สัมพัทธ์ไปยังไดเร็กทอรีย่อยจะไม่ทำงาน โปรดดูคำตอบของฉันเกี่ยวกับวิธีแก้ไขปัญหานี้
Russ

@Russ - OP getcwd()ของการใช้งานตัวอย่างเช่น ฉันอ่านคำอธิบายดั้งเดิมว่า "สัมพันธ์กับตำแหน่งที่ฉันเรียกใช้สคริปต์ไม่ว่าโค้ดจะอยู่ที่ใดก็ตาม"
orip

@orip - OP เพิ่ม 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 คุณต้องเพิ่ม\เมื่อเริ่มเส้นทางไฟล์

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'ซึ่งไม่พยายามที่จะ "หลบหนี" อักขระ
Ronald
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.