Câu hỏi Trong Python, làm thế nào để đọc một tập tin dòng-by-line vào một danh sách?


Làm cách nào để đọc từng dòng của một tệp trong Python và lưu trữ mỗi dòng dưới dạng một phần tử trong một danh sách?

Tôi muốn đọc từng dòng và nối thêm mỗi dòng vào cuối danh sách.


1703
2017-07-18 22:25


gốc




Các câu trả lời:


with open(fname) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content] 

1659
2017-07-18 22:28



Không sử dụng file.readlines() trong một for-loop, một đối tượng tập tin chính nó là đủ: lines = [line.rstrip('\n') for line in file] - jfs
Trong trường hợp bạn đang làm việc với Big Data bằng readlines() không hiệu quả vì nó có thể dẫn đến MemoryError. Trong trường hợp này, tốt hơn là lặp qua tệp bằng for line in f: và làm việc với từng line biến. - DarkCygnus
Tôi đã kiểm tra hồ sơ bộ nhớ của các cách khác nhau được đưa ra trong các câu trả lời bằng cách sử dụng thủ tục được đề cập đây. Việc sử dụng bộ nhớ tốt hơn nhiều khi mỗi dòng được đọc từ tệp và được xử lý, như được gợi ý bởi @DevShark đây. Giữ tất cả các dòng trong đối tượng bộ sưu tập là không phải một ý tưởng tốt nếu bộ nhớ là một hạn chế hoặc tập tin là lớn. Thời gian thực hiện tương tự trong cả hai phương pháp. - Tirtha R
Cũng thế, .rstrip() sẽ làm việc nhanh hơn một chút nếu bạn đang loại bỏ khoảng trắng từ cuối dòng. - Gringo Suave


Xem Đầu vào và Ouput:

with open('filename') as f:
    lines = f.readlines()

hoặc với tước ký tự dòng mới:

lines = [line.rstrip('\n') for line in open('filename')]

Ghi chú của biên tập viên: Lệnh tách biệt khoảng trắng ban đầu của câu trả lời này, line.strip(), như ngụ ý của bình luận của Janus Troelsen, sẽ xóa tất cả hàng đầu và cuối khoảng trắng, không chỉ là dấu \n.


781
2017-07-18 22:28



nếu bạn chỉ muốn hủy bỏ dòng mới: lines = (line.rstrip('\n') for line in open(filename)) - Janus Troelsen
Đối với một danh sách cần lines = [line.rstrip('\n') for line in open(filename)] - Lazik
Không phải tùy chọn thứ 2 sẽ để tệp mở (vì nó không được bảo vệ bởi một ngữ cảnh riêng)? - yo'
@yo 'Nó có, nhưng hầu hết mọi người không quan tâm đến điều đó trong các chương trình nhỏ. Không có hại trong các chương trình nhỏ vì đối tượng tệp bị rò rỉ là rác được thu thập, nhưng nó không phải là một thói quen tốt để làm điều này. - Martin Ueding
An toàn hơn: with open('filename') as f: lines = [line.rstrip('\n') for line in f] - becko


Điều này rõ ràng hơn mức cần thiết, nhưng thực hiện những gì bạn muốn.

with open("file.txt", "r") as ins:
    array = []
    for line in ins:
        array.append(line)

369
2017-07-18 22:27



Đây là câu trả lời trực tiếp cho câu hỏi - Joop


Điều này sẽ mang lại một "mảng" của các dòng từ tập tin.

lines = tuple(open(filename, 'r'))

206
2017-07-18 22:27



open trả về một tệp có thể được lặp lại. Khi bạn lặp qua một tệp, bạn sẽ nhận được các dòng từ tệp đó. tuple có thể lấy một trình lặp và khởi tạo một thể hiện tuple cho bạn từ trình lặp mà bạn cung cấp cho nó. lines là một bộ tuple được tạo từ các dòng của tệp. - Noctis Skytower
@MarshallFarrier Try lines = open(filename).read().split('\n') thay thế. - Noctis Skytower
nó đóng tập tin? - Vanuan
@NoctisSkytower Tôi tìm thấy lines = open(filename).read().splitlines() một chút sạch hơn, và tôi tin rằng nó cũng xử lý kết thúc dòng DOS tốt hơn. - jaynp
@ mklement0 Giả sử một tệp 1000 dòng, một list chiếm khoảng 13,22% không gian hơn một tuple. Kết quả đến từ from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). Tạo ra một tuple mất khoảng 4,17% thời gian nhiều hơn là tạo list (với độ lệch chuẩn 0,16%). Kết quả đến từ hoạt động from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2) 30 lần. Giải pháp của tôi ủng hộ không gian trên tốc độ khi nhu cầu về khả năng đột biến chưa được biết. - Noctis Skytower


Nếu bạn muốn \n bao gồm:

with open(fname) as f:
    content = f.readlines()

Nếu bạn không muốn \n bao gồm:

with open(fname) as f:
    content = f.read().splitlines()

150
2018-03-02 04:22





Bạn có thể chỉ cần làm như sau, như đã được đề xuất:

with open('/your/path/file') as f:
    my_lines = f.readlines()

Lưu ý rằng cách tiếp cận này có 2 nhược điểm:

1) Bạn lưu trữ tất cả các dòng trong bộ nhớ. Trong trường hợp chung, đây là một ý tưởng rất tồi. Tệp có thể rất lớn và bạn có thể hết bộ nhớ. Ngay cả khi nó không lớn, nó chỉ đơn giản là một sự lãng phí bộ nhớ.

2) Điều này không cho phép xử lý từng dòng khi bạn đọc chúng. Vì vậy, nếu bạn xử lý các dòng của bạn sau này, nó không phải là hiệu quả (yêu cầu hai lần thay vì một).

Một cách tiếp cận tốt hơn cho trường hợp chung sẽ như sau:

with open('/your/path/file') as f:
    for line in f:
        process(line)

Nơi bạn xác định chức năng quy trình của mình theo bất kỳ cách nào bạn muốn. Ví dụ:

def process(line):
    if 'save the world' in line.lower():
         superman.save_the_world()

(Việc thực hiện Superman lớp còn lại là một bài tập cho bạn).

Điều này sẽ làm việc độc đáo cho bất kỳ kích thước tập tin và bạn đi qua tập tin của bạn chỉ trong 1 vượt qua. Đây thường là cách phân tích cú pháp chung sẽ hoạt động.


93
2018-02-25 09:13



Đây chính xác là những gì tôi cần - và cảm ơn vì đã giải thích những nhược điểm. Là một người mới bắt đầu bằng Python, thật tuyệt vời khi hiểu tại sao giải pháp là giải pháp. Chúc mừng! - Ephexx
Hãy suy nghĩ thêm một chút Corey. Bạn có thực sự muốn máy tính của bạn đọc từng dòng, không bao giờ làm bất cứ điều gì với những dòng này? Chắc chắn bạn có thể nhận ra bạn luôn cần phải xử lý chúng theo cách này hay cách khác. - DevShark
Bạn luôn luôn cần phải làm một cái gì đó với các dòng. Nó có thể đơn giản như in các dòng, hoặc đếm chúng. Không có giá trị trong quá trình của bạn đọc các dòng trong bộ nhớ, nhưng không làm bất cứ điều gì với nó. - DevShark
Bạn luôn cần phải làm điều gì đó với họ. Tôi nghĩ rằng điểm bạn đang cố gắng tạo ra là bạn có thể muốn áp dụng một hàm cho tất cả chúng cùng một lúc, chứ không phải từng cái một. Đó thực sự là trường hợp đôi khi. Nhưng nó là rất không hiệu quả từ một quan điểm bộ nhớ để làm như vậy, và ngăn cản bạn đọc các tập tin nếu dấu chân của nó lớn hơn Ram của bạn. Đó là lý do tại sao các trình phân tích cú pháp chung thường hoạt động theo cách tôi mô tả. - DevShark
@PierreOcinom đúng. Do tệp được mở ở chế độ chỉ đọc, bạn không thể sửa đổi tệp gốc bằng mã ở trên. Để mở một tệp cho cả đọc và viết, hãy sử dụng open('file_path', 'r+') - DevShark


Nếu bạn không quan tâm đến việc đóng tệp, công cụ này sẽ hoạt động:

lines = open('file.txt').read().split("\n")

Các truyên thông đường:

fp = open('file.txt') # Open file on read mode
lines = fp.read().split("\n") # Create a list containing all lines
fp.close() # Close file

Sử dụng with (được khuyến nghị):

with open('file.txt') as fp:
    lines = fp.read().split("\n")

61
2018-04-20 05:53



Nó có thể là tốt trong một số trường hợp, nhưng điều này không đóng tập tin, ngay cả sau khi vòng lặp đã hoàn thành - stackoverflow.com/a/1832589/232593 - Merlyn Morgan-Graham
Các with khối tự động đóng tệp. Không cần cho trận chung kết fp.close() trong ví dụ cuối cùng đó. Xem: repl.it/IMeA/0 - Merlyn Morgan-Graham
Luôn quan tâm đến việc đóng tệp! Hãy là một công dân tài nguyên tốt! - Nick


Điều này sẽ đóng gói lệnh mở.

array = []
with open("file.txt", "r") as f:
  for line in f:
    array.append(line)

38
2017-10-28 15:40



f.readlines () cũng vậy. không cần phải thêm vào một danh sách trống. - Corey Goldberg
Bạn đúng rồi. Điều này cung cấp cái nhìn sâu sắc vào một giải pháp nếu bạn muốn làm một cái gì đó trong khi bạn đang đọc trong các dòng. Giống như một số chuyển đổi dải / regex. - cevaris


Dữ liệu vào danh sách

Giả sử rằng chúng tôi có một tệp văn bản với dữ liệu của chúng tôi như trong các dòng sau:

Nội dung tệp văn bản:

   line 1
   line 2
   line 3
  • Mở cmd trong cùng thư mục (nhấn chuột phải và chọn cmd hoặc PowerShell)
  • Chạy python và trong thông dịch viên viết:

Kịch bản Python

>>> with open("myfile.txt", encoding="utf-8") as file:
...     x = [l.strip() for l in file]
>>> x
['line 1','line 2','line 3']

Sử dụng phụ thêm

x = []
with open("myfile.txt") as file:
    for l in file:
        x.append(l.strip())

Hoặc là...

>>> x = open("myfile.txt").read().splitlines()
>>> x
['line 1', 'line 2', 'line 3']

Hoặc là...

>>> y = [x.rstrip() for x in open("my_file.txt")]
>>> y
['line 1','line 2','line 3']

36
2018-04-26 04:57



là encoding="utf-8" cần thiết? - Mausy5043
@ Mausy5043 không, nhưng khi bạn đọc một tập tin văn bản, bạn có thể có một số ký tự lạ (expecially trong tiếng ý) - Giovanni Gianni