Làm thế nào để đọc từng dòng một tệp vào danh sách?


2027

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

Tôi muốn đọc từng dòng tệp và nối từng dòng vào cuối danh sách.

Câu trả lời:


2174
with open(filename) 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] 

206
Không sử dụng file.readlines()trong một for-loop, bản thân một đối tượng tệp là đủ:lines = [line.rstrip('\n') for line in file]
jfs

88
Trong trường hợp bạn đang làm việc với Big Data, việc sử dụng readlines()không hiệu quả lắm vì nó có thể dẫn đến MemoryError . Trong trường hợp này, tốt hơn là lặp lại tập tin bằng cách sử dụng for line in f:và làm việc với từng linebiến.
DarkCygnus

7
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 quy trình được đề cập ở đây . Việc sử dụng bộ nhớ sẽ tốt hơn nhiều khi mỗi dòng được đọc từ tệp và được xử lý, như được đề xuất bởi @DevShark tại đây . Giữ tất cả các dòng trong một đối tượng bộ sưu tập không phải là một ý tưởng tốt nếu bộ nhớ là một ràng buộc hoặc tệp lớn. Thời gian thực hiện là tương tự trong cả hai phương pháp.
Tirtha R

6
Ngoài ra, .rstrip()sẽ hoạt động nhanh hơn một chút nếu bạn tước khoảng trắng từ cuối dòng.
Gringo Suave

Oneliner:with open(filename) as f: content = [i.strip() for i in f.readlines()]
Vishal Gupta

1002

Xem Đầu vào và Ouput :

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

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

with open('filename') as f:
    lines = [line.rstrip() for line in f]

12
Tốt hơn, sử dụng f.read().splitlines(), loại bỏ các dòng mới
Đánh dấu

Là phiên bản thứ hai, với for line in open(filename)an toàn? Đó là, tập tin sẽ được tự động đóng?
vẫy gọi

2
Tốt nhất nên đọc từng dòng một tệp thay vì đọc toàn bộ tệp vào bộ nhớ cùng một lúc. Làm như vậy không quy mô tốt với các tập tin đầu vào lớn. Xem câu trả lời dưới đây của robert.
Brad Hein

1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]Nếu tôi viết theo cách này, làm thế nào tôi có thể đóng tệp sau khi đọc?
Ramisa Anjum Aditi

2
Vâng, đến thời điểm mà những người khác đang thực hiện ở đây, trong khi đó không phải là "cách tốt nhất" để sử dụng openmà không có trình quản lý bối cảnh (hoặc một số cách được bảo đảm khác để đóng nó), đây thực sự không phải là một trong những trường hợp đó - khi đối tượng không có thêm tài liệu tham khảo với nó, nó sẽ là rác được thu thập và đóng tệp, điều này có xảy ra ngay lập tức khi có lỗi hay không, khi việc hiểu danh sách được xử lý xong.
Aaron Hall

579

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

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)

18
Tôi thích câu trả lời này vì nó không yêu cầu tải toàn bộ tệp vào bộ nhớ (trong trường hợp này nó vẫn được thêm vào array, nhưng có thể có các trường hợp khác). Chắc chắn đối với các tệp lớn, phương pháp này có thể giảm thiểu các vấn đề.
JohannesB

1
Nối vào một mảng là chậm. Tôi không thể nghĩ về một trường hợp sử dụng trong đó đây là giải pháp tốt nhất.
Elias Stroundle

@haccks là tốt hơn bởi vì nó không tải toàn bộ tập tin vào bộ nhớ hoặc có nhiều hơn?
OrigamiEye

4
Lưu ý: Giải pháp này không loại bỏ dòng mới.
AMC

1
Giải pháp này không tải toàn bộ tập tin vào bộ nhớ. Tôi không biết tại sao mọi người nghĩ rằng nó không.
andreb Eo

274

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

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

opentrả về một tập tin có thể được lặp đi lặp lại. Khi bạn lặp lại một tệp, bạn sẽ nhận được các dòng từ tệp đó. tuplecó thể lấy một trình vòng lặp và khởi tạo một thể hiện tuple cho bạn từ trình vòng lặp mà bạn đưa ra. lineslà một tuple được tạo từ các dòng của tệp.


31
@MarshallFarrier Hãy thử lines = open(filename).read().split('\n')thay thế.
Noctis Skytower

16
nó đóng tập tin?
Vanuan

5
@Vanuan Vì không còn tham chiếu đến tệp sau khi dòng được chạy, nên hàm hủy sẽ tự động đóng tệp.
Noctis Skytower

30
@NoctisSkytower Tôi thấy lines = open(filename).read().splitlines()sạch hơn một chút và tôi tin rằng nó cũng xử lý các kết thúc dòng DOS tốt hơn.
jaynp

8
@ mkuity0 Giả sử một tệp gồm 1000 dòng, a listchiếm khoảng 13,22% dung lượng so với a 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 một tuplemất nhiều thời gian hơn khoảng 4,17% so với việc tạo một list(với độ lệch chuẩn 0,16%). Kết quả đến từ việc chạy 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 hơn tốc độ khi không biết nhu cầu về tính đột biến.
Noctis Skytower

194

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

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

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

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

168

Theo Phương thức đối tượng tệp của Python , cách đơn giản nhất để chuyển đổi tệp văn bản thành list:

with open('file.txt') as f:
    my_list = list(f)

Nếu bạn chỉ cần lặp lại các dòng tệp văn bản, bạn có thể sử dụng:

with open('file.txt') as f:
    for line in f:
       ...

Câu trả lời cũ:

Sử dụng withreadlines():

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

Nếu bạn không quan tâm đến việc đóng tệp, thì lớp lót này hoạt động:

lines = open('file.txt').readlines()

Cách truyền thống :

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

150

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

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

Lưu ý rằng phương pháp 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 xấu. Các tập tin 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à 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 hiệu quả (yêu cầu hai lần chứ không phải một).

Một cách tiếp cận tốt hơn cho trường hợp chung sẽ là 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 bạn 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 Supermanlớp học được để lại như một bài tập cho bạn).

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


5
Đâ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à người mới bắt đầu sử dụng Python, thật tuyệt vời khi hiểu tại sao giải pháp lại là giải pháp. Chúc mừng!
Ephexx

5
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, mà 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 xử lý chúng bằng cách này hay cách khác.
DevShark

5
Bạ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 việc quá trình của bạn đọc các dòng trong bộ nhớ, nhưng không làm gì với nó.
DevShark

2
Bạn luôn cần phải làm một cái gì đó với họ. Tôi nghĩ rằng điểm bạn đang cố gắng thực hiện là bạn có thể muốn áp dụng một chức năng cho tất cả chúng cùng một lúc, thay vì từng cái một. Đó thực sự là trường hợp đôi khi. Nhưng nó rất không hiệu quả từ quan điểm bộ nhớ để làm như vậy và ngăn bạn đọc các tệp 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

2
@PierreOcinom đó là chính xác. Cho rằng tệp được mở ở chế độ chỉ đọc, bạn không thể sửa đổi tệp gốc với mã ở trên. Để mở tệp cho cả đọc và viết, hãy sử dụngopen('file_path', 'r+')
DevShark

65

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ấp chuột phải và chọn cmd hoặc PowerShell)
  • Chạy pythonvà trong trình thông dịch viết:

Kịch bản Python:

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

Sử dụng phụ lục:

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à:

>>> x = open("myfile.txt").readlines()
>>> x
['linea 1\n', 'line 2\n', 'line 3\n']

Hoặc là:

def print_output(lines_in_textfile):
    print("lines_in_textfile =", lines_in_textfile)

y = [x.rstrip() for x in open("001.txt")]
print_output(y)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
    print_output(file)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = [x.rstrip("\n") for x in file]
    print_output(file)

đầu ra:

lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']

1
read().splitlines()được Python cung cấp cho bạn: nó đơn giản readlines()(có thể nhanh hơn, vì nó ít lãng phí hơn).
Eric O Lebigot

1
@EricOLebigot từ các ví dụ được hiển thị, có vẻ như read().splitlines()readlines()không tạo ra cùng một đầu ra. Bạn có chắc là chúng tương đương?
craq

1
Nếu bạn chỉ sử dụng các đường dẫn, bạn cần sử dụng phương thức dải để loại bỏ \ n trong văn bản, vì vậy tôi đã thay đổi các ví dụ cuối bằng cách sử dụng cách hiểu danh sách để có cùng một đầu ra trong cả hai trường hợp. Vì vậy, nếu bạn sử dụng read (). Readlines (), bạn sẽ có một mục "sạch" với dòng và không có characther dòng mới, nếu không, bạn phải làm những gì bạn thấy trong đoạn mã trên.
Giovanni G. PY

1
Thật. Lưu ý rằng trong mã trên tất cả strip()nên rstrip("\n")hoặc khoảng trắng xung quanh một dòng bị xóa. Ngoài ra, không có điểm nào trong việc readlines()hiểu danh sách: chỉ cần lặp qua tập tin là tốt hơn, vì nó không lãng phí thời gian và bộ nhớ bằng cách tạo một danh sách trung gian của các dòng.
Eric O Lebigot

1
@EricOLebigot Xong, cảm ơn.
Giovanni G. PY

43

Để đọc một tập tin vào một danh sách, bạn cần làm ba điều:

  • Mở tập tin
  • Đọc tập tin
  • Lưu trữ nội dung dưới dạng danh sách

May mắn thay, Python giúp bạn thực hiện những điều này rất dễ dàng, vì vậy cách ngắn nhất để đọc tệp vào danh sách là:

lst = list(open(filename))

Tuy nhiên tôi sẽ thêm một số giải thích.

Mở tập tin

Tôi giả sử rằng bạn muốn mở một tệp cụ thể và bạn không giao dịch trực tiếp với xử lý tệp (hoặc xử lý giống như tệp). Hàm được sử dụng phổ biến nhất để mở tệp trong Python là open, nó cần một đối số bắt buộc và hai đối số tùy chọn trong Python 2.7:

  • Tên tệp
  • Chế độ
  • Bộ đệm (Tôi sẽ bỏ qua đối số này trong câu trả lời này)

Tên tệp phải là một chuỗi đại diện cho đường dẫn đến tệp . Ví dụ:

open('afile')   # opens the file named afile in the current working directory
open('adir/afile')            # relative path (relative to the current working directory)
open('C:/users/aname/afile')  # absolute path (windows)
open('/usr/local/afile')      # absolute path (linux)

Lưu ý rằng phần mở rộng tập tin cần phải được chỉ định. Điều này đặc biệt quan trọng đối với người dùng Windows vì phần mở rộng tập tin thích .txthoặc .doc, vv được ẩn theo mặc định khi xem trong thám hiểm.

Đối số thứ hai là mode, rtheo mặc định, nó có nghĩa là "chỉ đọc". Đó chính xác là những gì bạn cần trong trường hợp của bạn.

Nhưng trong trường hợp bạn thực sự muốn tạo một tệp và / hoặc ghi vào một tệp, bạn sẽ cần một đối số khác ở đây. Có một câu trả lời tuyệt vời nếu bạn muốn có một cái nhìn tổng quan .

Để đọc một tập tin, bạn có thể bỏ qua modehoặc chuyển nó một cách rõ ràng:

open(filename)
open(filename, 'r')

Cả hai sẽ mở tệp ở chế độ chỉ đọc. Trong trường hợp bạn muốn đọc tệp nhị phân trên Windows, bạn cần sử dụng chế độ rb:

open(filename, 'rb')

Trên các nền tảng khác, 'b'(chế độ nhị phân) đơn giản là bị bỏ qua.


Bây giờ tôi đã chỉ cho bạn cách opentập tin, hãy nói về thực tế là bạn luôn cần closenó một lần nữa. Mặt khác, nó sẽ giữ một tệp xử lý tệp mở cho tệp cho đến khi quá trình thoát (hoặc Python thu thập xử lý tệp).

Trong khi bạn có thể sử dụng:

f = open(filename)
# ... do stuff with f
f.close()

Điều đó sẽ không đóng tệp khi một cái gì đó giữa opencloseném một ngoại lệ. Bạn có thể tránh điều đó bằng cách sử dụng một tryfinally:

f = open(filename)
# nothing in between!
try:
    # do stuff with f
finally:
    f.close()

Tuy nhiên Python cung cấp các trình quản lý bối cảnh có cú pháp đẹp hơn (nhưng đối với opennó gần như giống hệt với tryfinallyở trên):

with open(filename) as f:
    # do stuff with f
# The file is always closed after the with-scope ends.

Cách tiếp cận cuối cùng là cách tiếp cận được đề xuất để mở tệp bằng Python!

Đọc tập tin

Được rồi, bạn đã mở tập tin, bây giờ làm thế nào để đọc nó?

Các openchức năng trả về một fileđối tượng và nó hỗ trợ giao thức lặp Trăn. Mỗi lần lặp sẽ cung cấp cho bạn một dòng:

with open(filename) as f:
    for line in f:
        print(line)

Điều này sẽ in từng dòng của tập tin. Tuy nhiên, xin lưu ý rằng mỗi dòng sẽ chứa một ký tự dòng mới \nở cuối (bạn có thể muốn kiểm tra xem Python của bạn có được xây dựng với hỗ trợ dòng mới phổ quát hay không - nếu không bạn cũng có thể có \r\ntrên Windows hoặc \rtrên Mac dưới dạng dòng mới). Nếu bạn không muốn rằng bạn có thể chỉ cần xóa ký tự cuối cùng (hoặc hai ký tự cuối cùng trên Windows):

with open(filename) as f:
    for line in f:
        print(line[:-1])

Nhưng dòng cuối cùng không nhất thiết phải có một dòng mới, vì vậy người ta không nên sử dụng dòng đó. Người ta có thể kiểm tra nếu nó kết thúc bằng một dòng mới và nếu vậy hãy loại bỏ nó:

with open(filename) as f:
    for line in f:
        if line.endswith('\n'):
            line = line[:-1]
        print(line)

Nhưng bạn chỉ có thể loại bỏ tất cả các khoảng trắng (bao gồm cả \nký tự) từ cuối chuỗi , điều này cũng sẽ loại bỏ tất cả các dấu khoảng trắng, do đó bạn phải cẩn thận nếu đây là những quan trọng:

with open(filename) as f:
    for line in f:
        print(f.rstrip())

Tuy nhiên, nếu các dòng kết thúc bằng \r\n(Windows "dòng mới") .rstrip()cũng sẽ chăm sóc \r!

Lưu trữ nội dung dưới dạng danh sách

Bây giờ bạn đã biết cách mở tệp và đọc nó, đã đến lúc lưu trữ nội dung trong danh sách. Tùy chọn đơn giản nhất sẽ là sử dụng listchức năng:

with open(filename) as f:
    lst = list(f)

Trong trường hợp bạn muốn loại bỏ các dòng mới, bạn có thể sử dụng cách hiểu danh sách thay thế:

with open(filename) as f:
    lst = [line.rstrip() for line in f]

Hoặc thậm chí đơn giản hơn: .readlines()Phương thức của fileđối tượng theo mặc định trả về một listtrong các dòng:

with open(filename) as f:
    lst = f.readlines()

Điều này cũng sẽ bao gồm các ký tự dòng mới, nếu bạn không muốn chúng, tôi sẽ khuyên bạn nên sử dụng [line.rstrip() for line in f]phương pháp này vì nó tránh giữ hai danh sách chứa tất cả các dòng trong bộ nhớ.

Có một tùy chọn bổ sung để có được đầu ra mong muốn, tuy nhiên đó là "tối ưu": readtệp hoàn chỉnh trong một chuỗi và sau đó phân chia trên dòng mới:

with open(filename) as f:
    lst = f.read().split('\n')

hoặc là:

with open(filename) as f:
    lst = f.read().splitlines()

Chúng tự động xử lý các dòng mới theo dõi vì splitký tự không được bao gồm. Tuy nhiên, chúng không lý tưởng vì bạn giữ tệp dưới dạng chuỗi và dưới dạng danh sách các dòng trong bộ nhớ!

Tóm lược

  • Sử dụng with open(...) as fkhi mở tệp vì bạn không cần phải tự đóng tệp và nó sẽ đóng tệp ngay cả khi có một số ngoại lệ xảy ra.
  • filecác đối tượng hỗ trợ giao thức lặp để đọc từng dòng tệp đơn giản như for line in the_file_object:.
  • Luôn duyệt tài liệu cho các chức năng / lớp có sẵn. Hầu hết thời gian có một kết hợp hoàn hảo cho nhiệm vụ hoặc ít nhất một hoặc hai cái tốt. Sự lựa chọn rõ ràng trong trường hợp này sẽ là readlines()nhưng nếu bạn muốn xử lý các dòng trước khi lưu chúng trong danh sách, tôi sẽ khuyên bạn nên hiểu danh sách đơn giản.

Cách tiếp cận cuối cùng là cách tiếp cận được đề xuất để mở tệp bằng Python! Tại sao nó là cuối cùng, sau đó? Không phải đại đa số mọi người chỉ lướt qua vài dòng đầu tiên của câu trả lời trước khi tiếp tục?
AMC

@AMC Tôi chưa nghĩ nhiều về nó khi tôi viết câu trả lời. Bạn có nghĩ rằng tôi nên đặt nó ở đầu câu trả lời?
MSeifert

Nó có thể là tốt nhất, yeah. Tôi cũng chỉ nhận thấy rằng bạn đề cập đến Python 2, do đó cũng có thể được cập nhật.
AMC

Ah câu hỏi ban đầu được gắn thẻ python-2.x. Nó có thể có ý nghĩa để cập nhật nó nói chung hơn. Tôi sẽ xem nếu tôi đến đó trong thời gian tới. Cảm ơn lời đề nghị của bạn. Nhiều đánh giá cao!
MSeifert

42

Cách sạch sẽ và Pythonic để đọc các dòng của tệp vào danh sách


Đầu tiên và quan trọng nhất, bạn nên tập trung vào việc mở tệp của mình và đọc nội dung của nó theo cách hiệu quả và pythonic. Đây là một ví dụ về cách cá nhân tôi KHÔNG thích:

infile = open('my_file.txt', 'r')  # Open the file for reading.

data = infile.read()  # Read the contents of the file.

infile.close()  # Close the file since we're done using it.

Thay vào đó, tôi thích phương pháp mở tệp dưới đây cho cả đọc và viết vì nó rất sạch sẽ và không yêu cầu thêm một bước đóng tệp sau khi bạn sử dụng xong. Trong tuyên bố dưới đây, chúng tôi đang mở tệp để đọc và gán nó cho biến 'infile'. Khi mã trong câu lệnh này đã chạy xong, tệp sẽ được tự động đóng lại.

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

Bây giờ chúng ta cần tập trung vào việc đưa dữ liệu này vào Danh sách Python vì chúng có thể lặp lại, hiệu quả và linh hoạt. Trong trường hợp của bạn, mục tiêu mong muốn là đưa từng dòng của tệp văn bản vào một thành phần riêng biệt. Để thực hiện điều này, chúng tôi sẽ sử dụng phương thức splitlines () như sau:

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Sản phẩm cuối cùng:

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Kiểm tra mã của chúng tôi:

  • Nội dung của tệp văn bản:
     A fost odatã ca-n povesti,
     A fost ca niciodatã,
     Din rude mãri împãrãtesti,
     O prea frumoasã fatã.
  • In báo cáo cho mục đích thử nghiệm:
    print my_list  # Print the list.

    # Print each line in the list.
    for line in my_list:
        print line

    # Print the fourth element in this list.
    print my_list[3]
  • Đầu ra (trông khác nhau vì các ký tự unicode):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,',
     'Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O prea
     frumoas\xc3\xa3 fat\xc3\xa3.']

     A fost odatã ca-n povesti, A fost ca niciodatã, Din rude mãri
     împãrãtesti, O prea frumoasã fatã.

     O prea frumoasã fatã.

30

Được giới thiệu trong Python 3.4, pathlibcó một phương pháp thực sự thuận tiện để đọc văn bản từ các tệp, như sau:

from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()

(Cuộc splitlinesgọi là những gì biến nó từ một chuỗi chứa toàn bộ nội dung của tệp thành một danh sách các dòng trong tệp).

pathlibcó rất nhiều tiện ích trong đó. read_textlà tốt đẹp và súc tích, và bạn không phải lo lắng về việc mở và đóng tệp. Nếu tất cả những gì bạn cần làm với tệp được đọc tất cả trong một lần, đó là một lựa chọn tốt.


29

Đây là một tùy chọn nữa bằng cách sử dụng danh sách hiểu trên các tệp;

lines = [line.rstrip() for line in open('file.txt')]

Đây phải là cách hiệu quả hơn vì phần lớn công việc được thực hiện bên trong trình thông dịch Python.


10
rstrip()có khả năng dải tất cả khoảng trắng theo sau, không chỉ \n; sử dụng .rstrip('\n').
mkuity0

Điều này cũng không đảm bảo rằng tệp sẽ được đóng sau khi đọc trong tất cả các triển khai Python (mặc dù trong CPython, triển khai Python chính, nó sẽ được).
Đánh dấu Amery

1
Đây phải là cách hiệu quả hơn vì phần lớn công việc được thực hiện bên trong trình thông dịch Python. Điều đó nghĩa là gì?
AMC

28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Bây giờ biến ra là một danh sách (mảng) của những gì bạn muốn. Bạn có thể làm:

for line in out:
    print (line)

Hoặc là:

for line in f:
    print (line)

Bạn sẽ nhận được kết quả tương tự.


27

Đọc và viết các tệp văn bản với Python 2 và Python 3; nó hoạt động với Unicode

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Define data
lines = ['     A first string  ',
         'A Unicode sample: €',
         'German: äöüß']

# Write text file
with open('file.txt', 'w') as fp:
    fp.write('\n'.join(lines))

# Read text file
with open('file.txt', 'r') as fp:
    read_lines = fp.readlines()
    read_lines = [line.rstrip('\n') for line in read_lines]

print(lines == read_lines)

Những điều cần chú ý:

  • withlà một người quản lý bối cảnh . Nó đảm bảo rằng tệp đã mở được đóng lại.
  • Tất cả các giải pháp ở đây chỉ đơn giản là thực hiện .strip()hoặc .rstrip()sẽ không thể tái tạo linesvì chúng cũng tước đi khoảng trắng.

Kết thúc tập tin phổ biến

.txt

Đọc / đọc tệp nâng cao hơn

Đối với ứng dụng của bạn, những điều sau đây có thể quan trọng:

  • Hỗ trợ bởi các ngôn ngữ lập trình khác
  • Hiệu suất đọc / viết
  • Tính gọn nhẹ (kích thước tệp)

Xem thêm: So sánh các định dạng tuần tự hóa dữ liệu

Trong trường hợp bạn muốn tìm cách tạo tệp cấu hình, bạn có thể muốn đọc các tệp Cấu hình bài viết ngắn của tôi bằng Python .


26

Một lựa chọn khác là numpy.genfromtxt, ví dụ:

import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")

Điều này sẽ tạo datamột mảng NumPy có nhiều hàng như trong tệp của bạn.


25

Nếu bạn muốn đọc một tệp từ dòng lệnh hoặc từ stdin, bạn cũng có thể sử dụng fileinputmô-đun:

# reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()

Truyền tệp cho nó như vậy:

$ python reader.py textfile.txt 

Đọc thêm tại đây: http://docs.python.org/2/l Library / fileinput.html


20

Cách đơn giản nhất để làm điều đó

Một cách đơn giản là:

  1. Đọc toàn bộ tập tin dưới dạng một chuỗi
  2. Tách dòng chuỗi theo dòng

Trong một dòng, điều đó sẽ cho:

lines = open('C:/path/file.txt').read().splitlines()

Tuy nhiên, đây là cách khá kém hiệu quả vì điều này sẽ lưu trữ 2 phiên bản nội dung trong bộ nhớ (có thể không phải là vấn đề lớn đối với các tệp nhỏ, nhưng vẫn còn). [Cảm ơn Mark Amery].

Có 2 cách dễ dàng hơn:

  1. Sử dụng tệp như một trình vòng lặp
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. Nếu bạn đang sử dụng Python 3.4 trở lên, tốt hơn nên sử dụng pathlibđể tạo đường dẫn cho tệp của bạn mà bạn có thể sử dụng cho các hoạt động khác trong chương trình của mình:
from pathlib import Path
file_path = Path("C:/path/file.txt") 
lines = file_path.read_text().split_lines()
# ... or ... 
lines = [l.rstrip() for l in file_path.open()]

Đây là một cách tiếp cận xấu. Đối với một điều, gọi .read().splitlines()không theo bất kỳ cách nào "đơn giản" hơn là chỉ gọi .readlines(). Mặt khác, đó là bộ nhớ không hiệu quả; bạn không cần lưu trữ hai phiên bản của nội dung tệp (chuỗi đơn được trả về .read()và danh sách các chuỗi được trả về splitlines()) trong bộ nhớ cùng một lúc.
Đánh dấu Amery

@MarkAmery Đúng. Cảm ơn đã làm nổi bật điều này. Tôi đã cập nhật câu trả lời của tôi.
Jean-Francois T.

14

Chỉ cần sử dụng các hàm splitlines (). Đây là một ví dụ.

inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3

Trong đầu ra, bạn sẽ có danh sách các dòng.


Bộ nhớ không hiệu quả so với sử dụng .readlines(). Điều này đặt hai bản sao của nội dung tệp vào bộ nhớ cùng một lúc (một dưới dạng một chuỗi lớn, một dưới dạng danh sách các dòng).
Đánh dấu Amery

11

Nếu bạn muốn đối mặt với một tệp rất lớn / khổng lồ và muốn đọc nhanh hơn (hãy tưởng tượng bạn đang tham gia cuộc thi mã hóa Topcoder / Hackerrank), thay vào đó, bạn có thể đọc một đoạn lớn hơn đáng kể vào bộ nhớ đệm chỉ lặp lại theo từng dòng ở cấp độ tập tin.

buffersize = 2**16
with open(path) as f: 
    while True:
        lines_buffer = f.readlines(buffersize)
        if not lines_buffer:
            break
        for line in lines_buffer:
            process(line)

quá trình (dòng) làm gì? Tôi nhận được một lỗi rằng không có biến như vậy được xác định. Tôi đoán một cái gì đó cần nhập và tôi đã cố gắng nhập đa xử lý. Xử lý, nhưng đó không phải là tôi đoán. Bạn có thể vui lòng giải thích? Cảm ơn
Newskooler

1
process(line)là một chức năng mà bạn cần thực hiện để xử lý dữ liệu. ví dụ, thay vì dòng đó, nếu bạn sử dụng print(line), nó sẽ in từng dòng từ lines_buffer.
Khanal

f.readlines (đệm) trả về một bộ đệm bất biến. nếu bạn muốn đọc trực tiếp vào bộ đệm của mình, bạn cần sử dụng hàm readinto (). Tôi sẽ nhanh hơn nhiều.
David Deh Afghanistan

7

Các cách dễ nhất để làm điều đó với một số lợi ích bổ sung là:

lines = list(open('filename'))

hoặc là

lines = tuple(open('filename'))

hoặc là

lines = set(open('filename'))

Trong trường hợp với set, chúng ta phải nhớ rằng chúng ta không giữ trật tự dòng và loại bỏ các dòng trùng lặp.

Dưới đây tôi đã thêm một bổ sung quan trọng từ @MarkAmery :

Vì bạn không gọi .closeđối tượng tệp cũng như không sử dụng withcâu lệnh, nên trong một số triển khai Python , tệp có thể không bị đóng sau khi đọc và quá trình của bạn sẽ rò rỉ xử lý tệp mở .

Trong CPython (cách triển khai Python bình thường mà hầu hết mọi người sử dụng), đây không phải là vấn đề vì đối tượng tệp sẽ được thu gom rác ngay lập tức và điều này sẽ đóng tệp, nhưng dù sao, nó thường được coi là cách thực hành tốt nhất để làm một việc như :

with open('filename') as f: lines = list(f) 

để đảm bảo rằng tệp được đóng bất kể bạn đang sử dụng triển khai Python nào.


1
Vì bạn không gọi .closeđối tượng tệp cũng như không sử dụng withcâu lệnh, nên trong một số triển khai Python, tệp có thể không bị đóng sau khi đọc và quá trình của bạn sẽ rò rỉ xử lý tệp mở. Trong CPython (cách triển khai Python bình thường mà hầu hết mọi người sử dụng), đây không phải là vấn đề vì đối tượng tệp sẽ được thu gom rác ngay lập tức và điều này sẽ đóng tệp, nhưng dù sao, nó thường được coi là cách thực hành tốt nhất with open('filename') as f: lines = list(f)để đảm bảo rằng tệp bị đóng bất kể bạn đang sử dụng triển khai Python nào.
Đánh dấu Amery

Cảm ơn bạn đã nhận xét tuyệt vời của bạn @MarkAmery! Tôi rất trân trọng điều này.
simhumileco

1
@simhumileco Tại sao có giải pháp (đúng) tốt nhất cuối cùng?
AMC

@AMC bởi vì trước tiên, tôi muốn chỉ ra những cách đơn giản nhất và cho sự nhất quán của lý luận.
simhumileco

Bên cạnh đó, tôi hy vọng câu trả lời của tôi được thực hiện sao cho nó ngắn gọn và dễ đọc.
simhumileco

4

Dùng cái này:

import pandas as pd
data = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.
array = data.values

datalà một kiểu khung dữ liệu và sử dụng các giá trị để lấy ndarray. Bạn cũng có thể có được một danh sách bằng cách sử dụng array.tolist().


pandas.read_csv()là để đọc dữ liệu CSV , làm thế nào là thích hợp ở đây?
AMC

4

Đề cương và Tóm tắt

Với một filename, xử lý tệp từ một Path(filename)đối tượng hoặc trực tiếp với open(filename) as f, thực hiện một trong các thao tác sau:

  • list(fileinput.input(filename))
  • sử dụng with path.open() as f, gọif.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • lặp qua fileinput.inputhay flist.appendmỗi một dòng tại một thời điểm
  • truyền fđến một list.extendphương thức ràng buộc
  • sử dụng ftrong một danh sách hiểu

Tôi giải thích trường hợp sử dụng cho mỗi bên dưới.

Trong Python, làm cách nào để đọc từng dòng tệp?

Đây là một câu hỏi tuyệt vời. Đầu tiên, hãy tạo một số dữ liệu mẫu:

from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')

Các đối tượng tệp là các trình vòng lặp lười biếng, vì vậy chỉ cần lặp qua nó.

filename = 'filename'
with open(filename) as f:
    for line in f:
        line # do something with the line

Ngoài ra, nếu bạn có nhiều tệp, hãy sử dụng fileinput.input, một trình vòng lặp lười biếng khác. Chỉ với một tệp:

import fileinput

for line in fileinput.input(filename): 
    line # process the line

hoặc cho nhiều tệp, chuyển cho nó một danh sách tên tệp:

for line in fileinput.input([filename]*2): 
    line # process the line

Một lần nữa, ffileinput.inputtrên cả hai là / trả lại các vòng lặp lười biếng. Bạn chỉ có thể sử dụng một trình vòng lặp một lần, vì vậy để cung cấp mã chức năng trong khi tránh tính dài dòng, tôi sẽ sử dụng một chút ngắn gọn hơn fileinput.input(filename)nơi apropos từ đây.

Trong Python, làm cách nào để đọc từng dòng tệp vào danh sách?

Ah nhưng bạn muốn nó trong một danh sách vì một số lý do? Tôi sẽ tránh điều đó nếu có thể. Nhưng nếu bạn cứ khăng khăng ... chỉ cần vượt qua là kết quả của fileinput.input(filename)để list:

list(fileinput.input(filename))

Một câu trả lời trực tiếp khác là gọi f.readlines, trong đó trả về nội dung của tệp (tối đa một hintsố ký tự tùy chọn , do đó bạn có thể chia thành nhiều danh sách theo cách đó).

Bạn có thể nhận được đối tượng tập tin này theo hai cách. Một cách là chuyển tên tệp cho opennội dung:

filename = 'filename'

with open(filename) as f:
    f.readlines()

hoặc sử dụng đối tượng Đường dẫn mới từ pathlibmô-đun (mà tôi đã trở nên khá yêu thích và sẽ sử dụng từ đây về sau):

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list cũng sẽ sử dụng trình lặp tệp và trả về một danh sách - một phương thức khá trực tiếp:

with path.open() as f:
    list(f)

Nếu bạn không đọc toàn bộ văn bản vào bộ nhớ dưới dạng một chuỗi trước khi tách nó, bạn có thể thực hiện điều này dưới dạng một lớp với Pathđối tượng và splitlines()phương thức chuỗi. Theo mặc định, splitlinesxóa các dòng mới:

path.read_text().splitlines()

Nếu bạn muốn giữ dòng mới, hãy vượt qua keepends=True:

path.read_text().splitlines(keepends=True)

Tôi muốn đọc từng dòng tệp và nối từng dòng vào cuối danh sách.

Bây giờ điều này hơi ngớ ngẩn khi yêu cầu, vì chúng tôi đã chứng minh kết quả cuối cùng một cách dễ dàng bằng một số phương pháp. Nhưng bạn có thể cần lọc hoặc vận hành trên các dòng khi bạn tạo danh sách của mình, vì vậy hãy hài hước yêu cầu này.

Việc sử dụng list.appendsẽ cho phép bạn lọc hoặc vận hành trên từng dòng trước khi bạn nối nó:

line_list = []
for line in fileinput.input(filename):
    line_list.append(line)

line_list

Việc sử dụng list.extendsẽ trực tiếp hơn một chút và có lẽ hữu ích nếu bạn có một danh sách có sẵn:

line_list = []
line_list.extend(fileinput.input(filename))
line_list

Hoặc thành ngữ hơn, thay vào đó chúng ta có thể sử dụng một sự hiểu biết danh sách, và ánh xạ và lọc bên trong nó nếu muốn:

[line for line in fileinput.input(filename)]

Hoặc thậm chí trực tiếp hơn, để đóng vòng tròn, chỉ cần chuyển nó vào danh sách để tạo danh sách mới trực tiếp mà không cần hoạt động trên các dòng:

list(fileinput.input(filename))

Phần kết luận

Bạn đã thấy nhiều cách để đưa các dòng từ một tệp vào danh sách, nhưng tôi khuyên bạn nên tránh việc cụ thể hóa một lượng lớn dữ liệu vào danh sách và thay vào đó hãy sử dụng phép lặp lười biếng của Python để xử lý dữ liệu nếu có thể.

Đó là, thích fileinput.inputhay with path.open() as f.


4

Trong trường hợp cũng có các dòng trống trong tài liệu tôi muốn đọc trong nội dung và chuyển qua filterđể ngăn các phần tử chuỗi trống

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))

1
Điều này là unpythonic, hãy cẩn thận.
AMC

3

Bạn cũng có thể sử dụng lệnh loadtxt trong NumPy. Điều này kiểm tra ít điều kiện hơn genfromtxt, vì vậy nó có thể nhanh hơn.

import numpy
data = numpy.loadtxt(filename, delimiter="\n")

2

Tôi thích sử dụng như sau. Đọc các dòng ngay lập tức.

contents = []
for line in open(filepath, 'r').readlines():
    contents.append(line.strip())

Hoặc sử dụng hiểu danh sách:

contents = [line.strip() for line in open(filepath, 'r').readlines()]

2
Không cần readlines(), mà thậm chí phải chịu một hình phạt bộ nhớ. Bạn có thể chỉ cần loại bỏ nó, khi lặp qua một tệp (văn bản) lần lượt cho từng dòng.
Eric O Lebigot

2
Bạn nên sử dụng một withcâu lệnh để mở (và hoàn toàn đóng) tệp.
Aran-Fey

2

Tôi sẽ thử một trong những phương pháp được đề cập dưới đây. Tệp ví dụ mà tôi sử dụng có tên dummy.txt. Bạn có thể tìm thấy các tập tin ở đây . Tôi đoán rằng tệp nằm trong cùng thư mục với mã (bạn có thể thay đổi fpathđể bao gồm tên tệp và đường dẫn thư mục phù hợp.)

Trong cả hai ví dụ được đề cập dưới đây, danh sách mà bạn muốn được đưa ra bởi lst.

1.> Phương pháp đầu tiên :

fpath = 'dummy.txt'
with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.> Trong phương thức thứ hai , người ta có thể sử dụng mô-đun csv.reader từ Thư viện chuẩn Python :

import csv
fpath = 'dummy.txt'
with open(fpath) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter='   ')
    lst = [row[0] for row in csv_reader] 

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

Bạn có thể sử dụng một trong hai phương pháp. Thời gian dành cho việc tạo ra lstgần như bằng nhau trong hai phương pháp.


1
Lợi thế của cách tiếp cận thứ hai là gì? Tại sao gọi một thư viện bổ sung, trong đó thêm vào các trường hợp cạnh (dấu phân cách và dấu ngoặc kép)?
Charlie Harding

Là gì delimiter=' 'lập luận gì?
AMC

2

Đây là lớp thư viện trợ giúp Python (3) mà tôi sử dụng để đơn giản hóa tệp I / O:

import os

# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
  f = open(file_path, mode)
  try:
    return callback(f)
  except Exception as e:
    raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
  finally:
    f.close()


class FileIO:
  # return the contents of a file
  def read(file_path, mode = "r"):
    return __file_handler(file_path, mode, lambda rf: rf.read())

  # get the lines of a file
  def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
    return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]

  # create or update a file (NOTE: can also be used to replace a file's original content)
  def write(file_path, new_content, mode = "w"):
    return __file_handler(file_path, mode, lambda wf: wf.write(new_content))

  # delete a file (if it exists)
  def delete(file_path):
    return os.remove() if os.path.isfile(file_path) else None

Sau đó, bạn sẽ sử dụng FileIO.lineschức năng, như thế này:

file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
  print("Line {}: {}".format(i + 1, line))

Hãy nhớ rằng các tham số mode( "r"theo mặc định) và filter_fn(kiểm tra các dòng trống theo mặc định) là tùy chọn.

Bạn thậm chí có thể loại bỏ read, writedeletecác phương thức và chỉ để lại FileIO.lineshoặc thậm chí biến nó thành một phương thức riêng biệt được gọi read_lines.


lines = FileIO.lines(path)thực sự đủ đơn giản hơn with open(path) as f: lines = f.readlines()để biện minh cho sự tồn tại của người trợ giúp này? Bạn đang lưu, như, 17 ký tự cho mỗi cuộc gọi. (Và hầu hết thời gian, vì lý do hiệu năng và bộ nhớ, bạn sẽ muốn lặp lại trực tiếp một đối tượng tệp thay vì đọc các dòng của nó vào danh sách, vì vậy bạn thậm chí sẽ không muốn sử dụng điều này thường xuyên!) thường là một người hâm mộ của việc tạo ra các chức năng tiện ích nhỏ, nhưng điều này với tôi cảm giác như nó không cần thiết phải tạo ra một cách mới để viết một cái gì đó ngắn và dễ dàng với thư viện tiêu chuẩn mang lại cho chúng ta.
Đánh dấu Amery

Ngoài những gì @MarkAmery nói, tại sao lại sử dụng một lớp cho việc này?
AMC

1

Phiên bản dòng lệnh

#!/bin/python3
import os
import sys
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
filename = dname + sys.argv[1]
arr = open(filename).read().split("\n") 
print(arr)

Chạy với:

python3 somefile.py input_file_name.txt
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.