Đọc tệp bằng Python

Giới thiệu

Để làm việc với dữ liệu được lưu trữ, xử lý tệp trở thành kiến ​​thức cốt lõi của mọi lập trình viên Python chuyên nghiệp. Ngay từ bản phát hành đầu tiên, cả việc đọc và ghi dữ liệu vào tệp đều là các tính năng được tích hợp sẵn của Python. So với các ngôn ngữ lập trình khác như C hoặc Java, nó khá đơn giản và chỉ yêu cầu một vài dòng mã. Hơn nữa, không có mô-đun bổ sung nào phải được tải để làm điều đó đúng cách.

Trong bài viết này, chúng tôi sẽ giải thích cách đọc tệp bằng Python thông qua các ví dụ. Một số ví dụ bao gồm đọc từng dòng một tệp, dưới dạng một đoạn (một số dòng được xác định tại một thời điểm) và đọc một tệp trong một lần. Ngoài ra, chúng tôi sẽ chỉ cho bạn một cách để chỉ đọc một dòng cụ thể từ tệp mà không cần tìm kiếm toàn bộ tệp.

Kiến thức cơ bản về tệp bằng Python

Các phương pháp phổ biến để thao tác với tệp là open() để mở một tệp, seek() để đặt vị trí hiện tại của tệp ở phần bù đã cho và close() để đóng đối tượng tệp khi bạn sử dụng xong. Tích hợp sẵn open() hàm trả về một trình xử lý tệp đại diện cho một đối tượng tệp được sử dụng để truy cập tệp để đọc, ghi hoặc thêm vào.

Khi mở một file để đọc, Python cần biết chính xác cách mở file đó bằng hệ thống. Có sẵn hai chế độ truy cập – đọc và đọc ở chế độ nhị phân. Các cờ tương ứng được sử dụng là 'r''rb'và phải được chỉ định khi mở tệp có cài sẵn open() chức năng. Chế độ đầu tiên bao gồm việc giải thích các ký tự đặc biệt như “CR” (trả về đầu dòng) và “LF” (nguồn cấp dữ liệu) để biểu thị ngắt dòng, trong khi chế độ nhị phân cho phép bạn đọc dữ liệu ở chế độ thô - nơi dữ liệu được lưu trữ nguyên trạng mà không cần giải thích thêm.

Khi bạn đã mở một tập tin, open() hàm sẽ trả về một đối tượng tệp cho bạn. Các đối tượng tệp này có các phương thức như read(), readline(), write(), tell()seek(). Mặc dù một số đối tượng tệp (hoặc đối tượng giống tệp) có nhiều phương thức hơn những phương thức được liệt kê ở đây, nhưng đây là những phương thức phổ biến nhất. Không phải tất cả các đối tượng tệp cần phải triển khai tất cả các phương thức tệp.

Đọc từng dòng một tệp

Ví dụ đầu tiên được lấy cảm hứng từ hai ngôn ngữ lập trình – C và C++. Đây có lẽ là cách tiếp cận trực quan nhất – mở tệp bằng cách sử dụng open() chức năng, đọc từng dòng một của tệp bằng cách sử dụng readline() và xuất dòng ngay sau khi đọc.

Đang được sử dụng ở đây là một while vòng lặp liên tục đọc từ tệp miễn là readline() phương thức tiếp tục trả về dữ liệu. Trong trường hợp đến cuối tệp (EOF), while vòng lặp dừng và đối tượng tệp bị đóng, giải phóng tài nguyên cho các chương trình khác sử dụng:


filename = "test.txt"

filehandle = open(filename, 'r')
while True:
    
    line = filehandle.readline()
    if not line:
        break
    print(line)


filehandle.close()

Như bạn có thể đã lưu ý, chúng tôi đã mở và đóng tệp một cách rõ ràng trong ví dụ này. Mặc dù trình thông dịch Python tự động đóng các tệp đã mở khi kết thúc quá trình thực thi chương trình Python, nhưng việc đóng tệp một cách rõ ràng qua close() là một phong cách lập trình tốt và không nên bị lãng quên.

Như một sự cải tiến, giao thức trình lặp thuận tiện đã được giới thiệu bằng Python 2.3. Điều này cho phép bạn đơn giản hóa readline vòng lặp:


filename = "test.txt"
for line in open(filename, 'r'):
    print(line)

Đang được sử dụng ở đây là một for vòng lặp kết hợp với in trình lặp. Dòng hiện tại được xác định với sự trợ giúp của in trình lặp, đọc từ tệp và nội dung của nó được xuất ra stdout. Python bao gồm việc mở và đóng tệp cho bạn khi nó nằm ngoài phạm vi. Mặc dù không hiệu quả, nhưng điều này cho phép bạn không phải đối phó với các trình xử lý tệp nữa.

Thật không may, đoạn mã trên ít rõ ràng hơn và dựa vào bộ sưu tập rác nội bộ của Python để xử lý việc đóng tệp.

Được giới thiệu trong Python 2.5, with lệnh đóng gói toàn bộ quá trình nhiều hơn và cũng xử lý việc mở và đóng tệp chỉ một lần trong toàn bộ khối mã phạm vi:


filename = "test.txt"
with open(filename, 'r') as filehandle:
    for line in filehandle:
        print(line)

Sự kết hợp của with tuyên bố và open() lệnh chỉ mở tệp một lần. Nếu thành công for vòng lặp được thực thi và nội dung của dòng được in trên stdout.

Hơn nữa, việc sử dụng with tuyên bố có một tác dụng phụ. Bên trong, trình thông dịch Python tạo ra một tryfinally-block để đóng gói việc đọc từ tệp. Ví dụ sau đây cho thấy những gì về cơ bản đang xảy ra nội bộ trong Python với with khối mã:

try:
    filehandle = open(filename, 'r')
    
finally:
    filehandle.close()

Đọc một tập tin dưới dạng các dòng

Cho đến nay, chúng tôi đã xử lý từng dòng một tệp. Điều này khá chậm đối với các tệp lớn và có thể được cải thiện bằng cách đọc nhiều dòng cùng một lúc. Để đạt được điều đó, islice() phương pháp từ lặp đi lặp lại mô-đun phát huy tác dụng. Ngoài ra, nó hoạt động như một trình lặp và trả về một phần dữ liệu bao gồm n các dòng. Ở cuối tệp, kết quả có thể ngắn hơn và cuối cùng, lệnh gọi sẽ trả về một danh sách trống:

from itertools import islice

filename = "test.txt"

number_of_lines = 5

with open(filename, 'r') as input_file:
    lines_cache = islice(input_file, number_of_lines)
   
    for current_line in lines_cache:
        print (current_line)

Đọc một dòng cụ thể từ một tệp

Sử dụng các phương pháp được hiển thị ở trên, chúng tôi cũng có thể thực hiện các hành động hữu ích khác, chẳng hạn như đọc một dòng cụ thể từ một tệp. Để làm điều này, chúng tôi sử dụng một bộ đếm và in dòng thích hợp khi chúng tôi đến nó trong khi lặp qua tệp:


filename = "test.txt"

line_number = 3
print (f"line {line_number} of {filename} is: ")

with open(filename, 'r') as filehandle:
current_line = 1
    for line in filehandle:
        if current_line == line_number:
            print(line)
            break
        current_line += 1

Điều này có thể đơn giản dễ hiểu nhưng dài hơn một chút so với các ví dụ trước. Nó có thể được rút ngắn bằng cách sử dụng bộ nhớ đệm mô-đun.

Ví dụ sau đây cho thấy cách đơn giản hóa mã bằng cách sử dụng getline() phương pháp. Nếu số dòng được yêu cầu nằm ngoài phạm vi các dòng hợp lệ trong tệp, thì getline() thay vào đó, phương thức trả về một chuỗi trống:


import linecache

filename = "test.txt"

line_number = 3

line = linecache.getline(filename, line_number)
print (f"line {line_number} of {filename}:")
print (line)

Đọc toàn bộ tệp cùng một lúc

Cuối cùng nhưng không kém phần quan trọng, chúng ta sẽ xem xét một trường hợp rất khác so với ví dụ trước – đọc toàn bộ tệp trong một lần.

Hãy nhớ rằng trong hầu hết các trường hợp, bạn phải có đủ bộ nhớ để đọc toàn bộ tệp, vì các ký tự không chiếm quá nhiều dung lượng nhưng lại gây mệt mỏi với các tệp lớn. Ví dụ sau đây sử dụng sự kết hợp của with tuyên bố, và read() phương pháp. Trong trường hợp này, chúng tôi sẽ sử dụng read() để tải nội dung tệp dưới dạng luồng dữ liệu:

Xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, các tiêu chuẩn được ngành công nghiệp chấp nhận và bảng lừa đảo đi kèm. Dừng lệnh Googling Git và thực sự học nó!


filename = "test.txt"

with open(filename, 'r') as filehandle:
    filecontent = filehandle.read()
    print (filecontent)

Python cũng cung cấp readlines() phương pháp này tương tự như readline() phương pháp từ ví dụ đầu tiên. Trái ngược với read(), nội dung tệp được lưu trữ trong một danh sách, trong đó mỗi dòng của nội dung là một mục:


filename = "test.txt"

with open(filename, 'r') as filehandle:
    filecontent = filehandle.readlines()
    for line in filecontent:
        print (line)

Trong khi readlines() sẽ đọc nội dung từ tệp cho đến khi nó chạm EOF, hãy nhớ rằng bạn cũng có thể giới hạn số lượng nội dung được đọc bằng cách cung cấp sizehint tham số, là số byte cần đọc.

Kết luận

Như thường lệ, có nhiều cách để đọc nội dung của tệp. Xét về tốc độ, tất cả chúng đều hơn hoặc kém nhau. Giải pháp nào phù hợp nhất với bạn tùy thuộc vào trường hợp sử dụng cụ thể của bạn. Chúng tôi nghĩ rằng sẽ khá hữu ích khi xem những gì có thể xảy ra và sau đó chọn giải pháp phù hợp nhất.

Mặc dù Python đơn giản hóa rất nhiều quá trình đọc tệp nhưng đôi khi nó vẫn có thể trở nên phức tạp, trong trường hợp đó tôi khuyên bạn nên xem qua tài liệu Python chính thức để biết thêm chi tiết.

Dấu thời gian:

Thêm từ xếp chồng lên nhau