Mở tệp ở vị trí tương đối trong Python


132

Giả sử mã python được thực thi trong thư mục windows trước không biết 'main' và bất cứ nơi nào mã được cài đặt khi chạy, nó cần truy cập vào thư mục 'main / 2091 / data.txt'.

Tôi nên sử dụng chức năng mở (vị trí) như thế nào? Nên là vị trí nào?

Biên tập :

Tôi thấy rằng mã đơn giản dưới đây sẽ hoạt động..có bất kỳ nhược điểm nào không?

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

1
Bạn đang sử dụng dấu gạch chéo ngược không thoát. Đó là một bất lợi.
orip

6
Một số nhược điểm. 1) Theo @orip, sử dụng dấu gạch chéo cho đường dẫn, ngay cả trên cửa sổ. Chuỗi của bạn sẽ không hoạt động. Hoặc sử dụng chuỗi thô như thế nào r"\2091\sample.txt". Hoặc thoát chúng như thế "\\2091\\sample.txt"(nhưng điều đó thật khó chịu). Ngoài ra, 2) bạn đang sử dụng getcwd () là đường dẫn bạn đã vào khi bạn thực thi tập lệnh. Tôi nghĩ rằng bạn muốn liên quan đến vị trí kịch bản (nhưng bây giờ đang tự hỏi). Và 3), luôn luôn sử dụng các os.pathhàm để thao tác các đường dẫn. Đường tham gia đường dẫn của bạn phải là os.path.join(os.getcwd(), file)4); là vô nghĩa
Nga

3
Và để có biện pháp tốt ... 5) sử dụng các trình bảo vệ ngữ cảnh để giữ sạch sẽ và tránh quên đóng tệp của bạn : with open(path, 'r+') as fp:. Xem ở đây để giải thích tốt nhất về các withtuyên bố tôi đã thấy.
Nga

bên cạnh sự chăm sóc cần thiết đối với dấu gạch chéo, như đã chỉ ra, có chức năng os.path.abspathgiúp dễ dàng lấy đường dẫn đầy đủ của đường dẫn tương đối để mở. tuyên bố cuối cùng trông như thế này:os.path.abspath('./2091/sample.txt')
OPMendeavor

Câu trả lời:


189

Với loại điều này, bạn cần phải cẩn thận thư mục làm việc thực tế của bạn là gì. Ví dụ: bạn không thể chạy tập lệnh từ thư mục chứa tập tin. Trong trường hợp này, bạn không thể chỉ sử dụng một đường dẫn tương đối.

Nếu bạn chắc chắn rằng tệp bạn muốn nằm trong thư mục con bên dưới nơi tập lệnh được đặt thực sự, bạn có thể sử dụng __file__để giúp bạn ra khỏi đây. __file__là đường dẫn đầy đủ đến nơi tập lệnh bạn đang chạy.

Vì vậy, bạn có thể nghịch ngợm với một cái gì đó như thế này:

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)

Tôi thấy rằng mã đơn giản dưới đây sẽ hoạt động..có bất kỳ nhược điểm nào không? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>

@Arash Nhược điểm của nó là cwd (thư mục làm việc hiện tại) có thể là bất cứ điều gì và không nhất thiết phải là nơi tập lệnh của bạn được đặt.
Cory Mawhorter

5
__file__là một đường dẫn tương đối (ít nhất là trên thiết lập của tôi, vì một số lý do) và bạn cần gọi os.path.abspath(__file__)trước. osx / homebrew 2.7
Cory Mawhorter 17/07/13

2
os.path.dirname ( tệp ) không hoạt động với tôi trong Python 2.7. Nó đang hiển thịNameError: name '__file__' is not defined
Soumendra

1
@Soumendra Tôi nghĩ bạn đang thử nó trong bảng điều khiển. Hãy thử nó trong một tệp * .py.
Enku

35

Mã này hoạt động tốt:

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)

Đối với tôi, việc truy cập tệp trong thư mục mẹ của thư mục hiện tại không hoạt động..có .. được thêm dưới dạng chuỗi ..
M. Paul

Không hoạt động trên Windows. Đường dẫn đến tệp là chính xác nhưng Python không tìm thấy "tệp không tìm thấy" và hiển thị đường dẫn có dấu phân cách \.
lonstar

26

Tôi đã tạo một tài khoản để tôi có thể làm rõ sự khác biệt mà tôi nghĩ rằng tôi đã tìm thấy trong phản hồi ban đầu của Russ.

Để tham khảo, câu trả lời ban đầu của ông là:

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

Đây là một câu trả lời tuyệt vời vì nó đang cố gắng tự động tạo một đường dẫn hệ thống tuyệt đối đến tệp mong muốn.

Cory Mawhorter nhận thấy đó __file__là một đường dẫn tương đối (nó cũng có trong hệ thống của tôi) và được đề xuất sử dụng os.path.abspath(__file__). os.path.abspathtuy nhiên, trả về đường dẫn tuyệt đối của tập lệnh hiện tại của bạn (tức là /path/to/dir/foobar.py)

Để sử dụng phương thức này (và cuối cùng tôi đã làm cho nó hoạt động như thế nào), bạn phải xóa tên tập lệnh khỏi cuối đường dẫn:

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)

Kết quả abs_file_path (trong ví dụ này) trở thành: /path/to/dir/2091/data.txt


14
Bạn thậm chí có thể kết hợp cả hai cách tiếp cận để đơn giản hơnos.path.dirname(os.path.abspath(__file__))
Luke Taylor

1
@LukeTaylor Thật vậy sẽ tốt hơn là cố gắng tự sao chép os.path.dirnamechức năng như tôi đã làm trong câu trả lời của tôi năm ngoái.
Grant Hulegaard

19

Nó phụ thuộc vào hệ điều hành bạn đang sử dụng. Nếu bạn muốn một giải pháp tương thích với cả Windows và * nix một cái gì đó như:

from os import path

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

nên làm việc tốt

Các path mô-đun có thể định dạng một con đường cho bất cứ điều gì hệ điều hành nó đang chạy trên. Ngoài ra, python xử lý các đường dẫn tương đối tốt, miễn là bạn có quyền chính xác.

Chỉnh sửa :

Như đã đề cập bởi kindall trong các bình luận, python có thể chuyển đổi giữa các đường dẫn kiểu unix và kiểu windows, vì vậy mã thậm chí đơn giản hơn sẽ hoạt động:

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

Điều đó đang được nói, pathmô-đun vẫn có một số chức năng hữu ích.


3
relpath()chuyển đổi một tên đường dẫn thành một đường dẫn tương đối. Vì nó đã là một con đường tương đối, nó sẽ không làm gì cả.
loại

Nó sẽ chuyển đổi nó từ một đường dẫn kiểu unix sang đường dẫn kiểu windows nếu thích hợp. Có một chức năng khác trong os.pathmô-đun sẽ là một lựa chọn tốt hơn?
Wilduck

1
Windows sẽ hoạt động tốt với đường dẫn kiểu UNIX. Ít nhất là loạt dựa trên NT sẽ (2000, XP, Vista, 7). Không cần chuyển đổi.
kindall

7
Câu trả lời này không hoàn toàn chính xác và sẽ gây ra vấn đề. Các đường dẫn tương đối theo mặc định liên quan đến thư mục làm việc hiện tại (đường dẫn tập lệnh được thực thi từ) và KHÔNG phải là vị trí tập lệnh thực tế. Bạn cần sử dụng __file__. Xin vui lòng xem câu trả lời của tôi.
Nga

Có phải tác giả của câu trả lời này đã nhầm lẫn os.path.relpath với os.path.abspath?
foobarbiru

15

Tôi dành nhiều thời gian để khám phá lý do tại sao mã của tôi không thể tìm thấy tệp của tôi chạy Python 3 trên hệ thống Windows. Vì vậy, tôi đã thêm. trước / và mọi thứ hoạt động tốt:

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')

Tốt hơn:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D

Tôi đã thử trên hệ điều hành Windows nhưng tôi không thành công.
Ângelo Polotto

Thú vị - bạn có thể in script_dir không? Sau đó chuyển nó thành đường dẫn tuyệt đối như trongscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D

Tôi sẽ thử điều đó, nếu tôi thành công, tôi sẽ thay đổi câu trả lời.
Ângelo Polotto

6

Mã số:

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

Giải trình:

Thư viện nhập khẩu:

import os

Sử dụng __file__để đạt được đường dẫn của tập lệnh hiện tại:

script_path = os.path.abspath(__file__)

Tách đường dẫn script thành nhiều mục:

path_list = script_path.split(os.sep)

Xóa mục cuối cùng trong danh sách (tệp tập lệnh thực tế):

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

Thêm đường dẫn của tệp tương đối:

rel_path = "main/2091/data.txt

Tham gia các mục danh sách và thêm tệp của đường dẫn tương đối:

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

Bây giờ bạn đã sẵn sàng làm bất cứ điều gì bạn muốn với tệp, chẳng hạn như:

file = open(path)

Thay vì path = "/".join(script_directory) + "/" + rel_pathbạn nên sử dụng mô-đun os như trong path = os.path.join(script_directory, rel_path). Thay vì phân tích thủ công đường dẫn bạn nên sử dụngscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D

3

Nếu tập tin nằm trong thư mục mẹ của bạn, vd. follower.txt, bạn chỉ cần sử dụngopen('../follower.txt', 'r').read()


3

Thử cái này:

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 đã giới thiệu một thư viện tiêu chuẩn mới để xử lý các tệp và đường dẫn được gọi là pathlib. Nó làm việc cho tôi!


2

Không chắc chắn nếu điều này làm việc ở khắp mọi nơi.

Tôi đang sử dụng ipython trong Ubuntu.

Nếu bạn muốn đọc tệp trong thư mục con của thư mục hiện tại:

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

tập lệnh của bạn nằm trong thư mục hiện tại, chỉ cần thử điều này:

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

1

Python chỉ truyền tên tệp mà bạn cung cấp cho hệ điều hành, nó sẽ mở nó. Nếu hệ điều hành của bạn hỗ trợ các đường dẫn tương đối như main/2091/data.txt(gợi ý: nó), thì nó sẽ hoạt động tốt.

Bạn có thể thấy rằng cách dễ nhất để trả lời một câu hỏi như thế này là thử nó và xem điều gì xảy ra.


2
Không đúng ... thư mục làm việc bên trong tập lệnh là vị trí bạn chạy tập lệnh từ đó, không phải vị trí của tập lệnh. Nếu bạn chạy tập lệnh từ nơi khác (có thể tập lệnh nằm trong đường dẫn hệ thống của bạn), đường dẫn tương đối đến thư mục con sẽ không hoạt động. Xin vui lòng xem câu trả lời của tôi về cách khắc phục điều này.
Nga

@Russ - ví dụ của OP sử dụng getcwd(). Tôi đọc mô tả ban đầu là "liên quan đến nơi tôi chạy tập lệnh, bất kể mã nằm ở đâu".
orip

@orip - OP đã thêm cuộc gọi getcwd () 3 giờ sau câu hỏi. Không có vấn đề ... di chuyển trên. :)
Nga

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

Khi tôi mới bắt đầu, tôi thấy những mô tả này hơi đáng sợ. Đầu tiên tôi sẽ thử For Windows

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

và điều này sẽ nâng cao một syntax error. Tôi đã sử dụng nhận được rất nhiều nhầm lẫn. Sau đó, một số lướt trên google. tìm thấy tại sao lỗi xảy ra.Viết cái này cho người mới bắt đầu

Đó là vì đường dẫn được đọc bằng Unicode, bạn chỉ cần thêm một \đường dẫn khi bắt đầu đường dẫn tệp

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

Và bây giờ nó hoạt động chỉ cần thêm \trước khi bắt đầu thư mục.


1
Dấu gạch chéo ngược là ký tự thoát cho một số ký tự. Nếu bạn tình cờ gặp phải \tnhư ví dụ \top\directory, thì '\ t' được hiểu là ký tự tab và 'mẹo' của bạn không thành công. Tùy chọn tốt nhất là sử dụng định dạng chuỗi thô r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'không cố gắng 'thoát' ký tự.
Ronald
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.