Làm thế nào để đọc một tệp lớn - từng dòng một?


536

Tôi muốn lặp lại qua từng dòng của toàn bộ tệp. Một cách để làm điều này là bằng cách đọc toàn bộ tệp, lưu nó vào danh sách, sau đó đi qua dòng quan tâm. Phương pháp này sử dụng rất nhiều bộ nhớ, vì vậy tôi đang tìm kiếm một giải pháp thay thế.

Mã của tôi cho đến nay:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

Thực thi mã này đưa ra một thông báo lỗi : device active.

Bất kỳ đề xuất?

Mục đích là để tính tương tự chuỗi cặp khôn ngoan, nghĩa là cho mỗi dòng trong tệp, tôi muốn tính khoảng cách Levenshtein với mỗi dòng khác.


4
Tại sao bạn cần đọc lại toàn bộ tệp cho mỗi dòng? Có lẽ nếu bạn nói những gì bạn đang cố gắng thực hiện thì ai đó có thể đề xuất một cách tiếp cận tốt hơn.
JJJ

Câu trả lời:


1269

Cách chính xác, đầy đủ của Pythonic để đọc tệp là như sau:

with open(...) as f:
    for line in f:
        # Do something with 'line'

Câu withlệnh xử lý việc mở và đóng tệp, bao gồm nếu một ngoại lệ được đưa ra trong khối bên trong. Đối tượng for line in fxử lý đối tượng tệp flà một lần lặp, tự động sử dụng bộ đệm I / O và quản lý bộ nhớ để bạn không phải lo lắng về các tệp lớn.

Nên có một - và tốt nhất là chỉ có một - cách rõ ràng để làm điều đó.


14
vâng, đây là phiên bản tốt nhất với python 2.6 trở lên
Simon Bergot

3
Cá nhân tôi thích máy phát điện & coroutines để xử lý các đường ống dữ liệu.
jldupont

4
Điều gì sẽ là chiến lược tốt nhất nếu một tệp là một tệp văn bản lớn nhưng với một dòng và ý tưởng là xử lý các từ?
mfcabrera

4
Ai đó có thể giải thích làm thế nào for line in f:là làm việc? Ý tôi là, làm thế nào lặp lại đối tượng tập tin là có thể?
gấu trúc

11
Nếu bạn lặp lại một đối tượng, Python sẽ tìm trong danh sách các phương thức đối tượng mà một phương thức đặc biệt được gọi __iter__, nó sẽ cho nó biết phải làm gì. Các đối tượng tệp định nghĩa phương thức đặc biệt này để trả về một trình vòng lặp qua các dòng. (Roughly.)
Katriel 10/2/2015

130

Hai cách hiệu quả bộ nhớ theo thứ tự xếp hạng (đầu tiên là tốt nhất) -

  1. sử dụng with- được hỗ trợ từ python 2.5 trở lên
  2. sử dụng yieldnếu bạn thực sự muốn kiểm soát số lượng cần đọc

1. sử dụng with

withlà cách pythonic đẹp và hiệu quả để đọc các tệp lớn. lợi thế - 1) đối tượng tập tin được tự động đóng sau khi thoát khỏi withkhối thực thi. 2) xử lý ngoại lệ bên trong withkhối. 3) forvòng lặp bộ nhớ lặp quaf dòng đối tượng tệp theo dòng. bên trong nó thực hiện đệm IO (để tối ưu hóa các hoạt động IO tốn kém) và quản lý bộ nhớ.

with open("x.txt") as f:
    for line in f:
        do something with data

2. sử dụng yield

Đôi khi người ta có thể muốn kiểm soát chi tiết hơn về số lượng cần đọc trong mỗi lần lặp. Trong trường hợp đó sử dụng iter & suất . Lưu ý với phương pháp này một cách rõ ràng cần đóng tệp ở cuối.

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.
    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chuck in readInChunks(f):
    do_something(chunk)
f.close()

Cạm bẫy và vì mục đích hoàn chỉnh - các phương pháp dưới đây không tốt hoặc không thanh lịch để đọc các tệp lớn nhưng vui lòng đọc để có được sự hiểu biết tròn trịa.

Trong Python, cách phổ biến nhất để đọc các dòng từ tệp là làm như sau:

for line in open('myfile','r').readlines():
    do_something(line)

Tuy nhiên, khi điều này được thực hiện, readlines()hàm (áp dụng tương tự cho read()hàm) sẽ tải toàn bộ tệp vào bộ nhớ, sau đó lặp lại qua nó. Một cách tiếp cận tốt hơn một chút (hai phương pháp được đề cập đầu tiên là tốt nhất) cho các tệp lớn là sử dụng fileinputmô-đun, như sau:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

các fileinput.input() cuộc gọi đọc dòng tuần tự, nhưng không giữ chúng trong bộ nhớ sau khi họ đã được đọc hoặc thậm chí chỉ đơn giản là vì vậy đây, vì filetrong python là iterable.

Người giới thiệu

  1. Python với tuyên bố

9
-1 Về cơ bản không bao giờ là một ý tưởng tốt để làm for line in open(...).readlines(): <do stuff>. Tại sao bạn?! Bạn vừa mất tất cả lợi ích của trình lặp IO được đệm thông minh của Python mà không có lợi ích.
Katriel

5
@Srikar: có một thời gian và một nơi để đưa ra tất cả các giải pháp có thể cho một vấn đề; dạy một người mới bắt đầu làm thế nào để làm tập tin đầu vào không phải là nó. Có câu trả lời đúng được chôn ở dưới cùng của một bài viết dài đầy câu trả lời sai không dạy tốt.
Katriel

6
@Srikar: Bạn có thể làm cho bài đăng của mình tốt hơn đáng kể bằng cách đặt đúng cách lên hàng đầu, sau đó đề cập readlinesvà giải thích lý do tại sao nó không phải là một việc nên làm (vì nó đọc tệp vào bộ nhớ), sau đó giải thích fileinputmô-đun làm gì và tại sao bạn có thể muốn sử dụng nó trên các phương thức khác, sau đó giải thích cách phân đoạn tệp làm cho IO tốt hơn và đưa ra một ví dụ về hàm phân đoạn (nhưng đề cập đến việc Python đã làm điều này cho bạn nên bạn không cần). Nhưng chỉ đưa ra năm cách để giải quyết một vấn đề đơn giản, bốn trong số đó là sai trong trường hợp này, là không tốt.
Katriel

2
Bất cứ điều gì bạn thêm vào vì mục đích hoàn chỉnh, hãy thêm nó lần cuối chứ không phải trước tiên. Đầu tiên chỉ ra cách thích hợp.
m000

6
@katrielalex xem lại câu trả lời của tôi và thấy rằng nó đảm bảo tái cấu trúc. Tôi có thể thấy làm thế nào câu trả lời trước đó có thể gây nhầm lẫn. Hy vọng điều này sẽ làm cho nó rõ ràng cho người dùng trong tương lai.
Srikar Appalaraju

37

Để loại bỏ các dòng mới:

with open(file_path, 'rU') as f:
    for line_terminated in f:
        line = line_terminated.rstrip('\n')
        ...

Với sự ủng hộ xuống dòng phổ quát tất cả các dòng tệp văn bản sẽ dường như được chấm dứt với '\n', bất kể Terminators trong file, '\r', '\n', hoặc '\r\n'.

EDIT - Để chỉ định hỗ trợ dòng mới phổ quát:

  • Python 2 trên Unix - open(file_path, mode='rU')- bắt buộc [cảm ơn @Dave ]
  • Python 2 trên Windows - open(file_path, mode='rU') - tùy chọn
  • Python 3 - open(file_path, newline=None)- tùy chọn

Các newlinetham số chỉ được hỗ trợ bằng Python 3 và mặc định None. Các modegiá trị mặc định tham số để 'r'trong mọi trường hợp. Cái Unày không được dùng trong Python 3. Trong Python 2 trên Windows, một số cơ chế khác xuất hiện để dịch \r\nsang\n .

Tài liệu:

Để bảo tồn các đầu cuối dòng gốc:

with open(file_path, 'rb') as f:
    with line_native_terminated in f:
        ...

Chế độ nhị phân vẫn có thể phân tích tệp thành các dòng với in . Mỗi dòng sẽ có bất kỳ dấu chấm dứt nào trong tệp.

Cảm ơn câu trả lời của @katrielalex , tài liệu open () của Python và iPython .


1
Trên Python 2.7 tôi phải open(file_path, 'rU')kích hoạt các dòng mới.
Dave

17

đây là một cách có thể để đọc một tập tin trong python:

f = open(input_file)
for line in f:
    do_stuff(line)
f.close()

nó không phân bổ một danh sách đầy đủ. Nó lặp đi lặp lại trên các dòng.


2
Trong khi điều này hoạt động, nó chắc chắn không phải là cách kinh điển. Cách chính tắc là sử dụng một trình bao bọc bối cảnh, như thế nào with open(input_file) as f:. Điều này giúp bạn tiết kiệm f.close()và đảm bảo bạn không vô tình quên đóng nó. Ngăn chặn rò rỉ bộ nhớ và tất cả, khá quan trọng khi đọc tệp.
Cột buồm

1
Như @Mast đã nói, đó không phải là cách kinh điển, vì vậy hãy downvote cho điều đó.
hoa anh thảo

12

Một số bối cảnh phía trước như nơi tôi đến. Đoạn mã ở cuối

Khi tôi có thể, tôi thích sử dụng một công cụ nguồn mở như H2O để đọc tệp CSV song song hiệu suất siêu cao, nhưng công cụ này bị giới hạn trong bộ tính năng. Tôi cuối cùng đã viết rất nhiều mã để tạo ra các đường ống khoa học dữ liệu trước khi cung cấp cho cụm H2O để học tập có giám sát.

Tôi đã đọc các tệp như bộ dữ liệu HIGGS 8GB từ repo UCI và thậm chí các tệp CSV 40 GB cho mục đích khoa học dữ liệu nhanh hơn đáng kể bằng cách thêm nhiều song song với đối tượng nhóm và thư viện của đối tượng đa xử lý. Ví dụ, phân cụm với các tìm kiếm lân cận gần nhất và các thuật toán phân cụm DBSCAN và Markov yêu cầu một số tinh chỉnh lập trình song song để bỏ qua một số vấn đề nghiêm trọng về bộ nhớ và đồng hồ treo tường.

Tôi thường thích chia hàng tệp thành các phần bằng cách sử dụng các công cụ gnu trước và sau đó toàn cầu hóa tất cả chúng để tìm và đọc chúng song song trong chương trình python. Tôi sử dụng một cái gì đó như 1000+ tập tin một phần thường gặp. Làm những thủ thuật này giúp ích rất nhiều với tốc độ xử lý và giới hạn bộ nhớ.

Các dataframe.read_csv của gấu trúc được phân luồng đơn để bạn có thể thực hiện các thủ thuật này để làm cho gấu trúc khá nhanh hơn bằng cách chạy bản đồ () để thực hiện song song. Bạn có thể sử dụng htop để thấy rằng với dataframe.read_csv tuần tự cũ đơn giản, 100% cpu trên chỉ một lõi là nút cổ chai thực sự trong pd.read_csv, hoàn toàn không phải là đĩa.

Tôi nên thêm Tôi đang sử dụng ổ SSD trên bus card video nhanh, không phải HD quay trên bus SATA6, cộng với 16 lõi CPU.

Ngoài ra, một kỹ thuật khác mà tôi phát hiện ra rất hiệu quả trong một số ứng dụng là tệp CSV song song đọc tất cả trong một tệp khổng lồ, bắt đầu mỗi công nhân ở độ lệch khác nhau vào tệp, thay vì chia trước một tệp lớn thành nhiều tệp. Sử dụng tệp tìm kiếm của python () và Tell () trong mỗi nhân viên song song để đọc tệp văn bản lớn theo dải, tại các vị trí bắt đầu byte và byte kết thúc byte khác nhau trong tệp lớn, đồng thời đồng thời. Bạn có thể thực hiện tìm kiếm regex trên byte và trả về số lượng nguồn cấp. Đây là một phần tổng. Cuối cùng tổng hợp một phần tổng để có được tổng toàn cầu khi hàm bản đồ trở lại sau khi các công nhân kết thúc.

Sau đây là một số điểm chuẩn ví dụ sử dụng thủ thuật bù byte song song:

Tôi sử dụng 2 tệp: HIGGS.csv là 8 GB. Nó là từ kho lưu trữ máy học UCI. all_bin .csv là 40,4 GB và là từ dự án hiện tại của tôi. Tôi sử dụng 2 chương trình: chương trình GNU wc đi kèm với Linux và chương trình fastread.txt thuần túy mà tôi đã phát triển.

HP-Z820:/mnt/fastssd/fast_file_reader$ ls -l /mnt/fastssd/nzv/HIGGS.csv
-rw-rw-r-- 1 8035497980 Jan 24 16:00 /mnt/fastssd/nzv/HIGGS.csv

HP-Z820:/mnt/fastssd$ ls -l all_bin.csv
-rw-rw-r-- 1 40412077758 Feb  2 09:00 all_bin.csv

ga@ga-HP-Z820:/mnt/fastssd$ time python fastread.py --fileName="all_bin.csv" --numProcesses=32 --balanceFactor=2
2367496

real    0m8.920s
user    1m30.056s
sys 2m38.744s

In [1]: 40412077758. / 8.92
Out[1]: 4530501990.807175

Đó là tốc độ giảm tốc của tệp 4,5 GB / giây hoặc 45 Gb / giây. Đó không phải là đĩa cứng quay, bạn của tôi. Đó thực sự là một ổ SSD Samsung Pro 950.

Dưới đây là điểm chuẩn tốc độ cho cùng một tệp được tính bởi dòng gnu wc, một chương trình được biên dịch C thuần túy.

Điều thú vị là bạn có thể thấy chương trình python thuần của tôi về cơ bản phù hợp với tốc độ của chương trình C được biên dịch gnu wc trong trường hợp này. Python được giải thích nhưng C được biên dịch, vì vậy đây là một kỳ tích khá thú vị về tốc độ, tôi nghĩ bạn sẽ đồng ý. Tất nhiên, wc thực sự cần phải được thay đổi thành một chương trình song song, và sau đó nó sẽ thực sự đánh bật tất khỏi chương trình python của tôi. Nhưng như ngày nay, gnu wc chỉ là một chương trình tuần tự. Bạn làm những gì bạn có thể, và python có thể làm song song ngày hôm nay. Biên dịch Cython có thể có thể giúp tôi (trong một thời gian khác). Ngoài ra các tập tin ánh xạ bộ nhớ chưa được khám phá.

HP-Z820:/mnt/fastssd$ time wc -l all_bin.csv
2367496 all_bin.csv

real    0m8.807s
user    0m1.168s
sys 0m7.636s


HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.257s
user    0m12.088s
sys 0m20.512s

HP-Z820:/mnt/fastssd/fast_file_reader$ time wc -l HIGGS.csv
11000000 HIGGS.csv

real    0m1.820s
user    0m0.364s
sys 0m1.456s

Kết luận: Tốc độ tốt cho chương trình python thuần so với chương trình C. Tuy nhiên, nó không đủ tốt để sử dụng chương trình python thuần so với chương trình C, ít nhất là cho mục đích linecounting. Nói chung kỹ thuật có thể được sử dụng để xử lý tệp khác, vì vậy mã python này vẫn tốt.

Câu hỏi: Việc biên dịch regex chỉ một lần và chuyển nó cho tất cả công nhân sẽ cải thiện tốc độ? Trả lời: Biên dịch trước Regex KHÔNG giúp ích gì trong ứng dụng này. Tôi cho rằng lý do là chi phí chung của quá trình tuần tự hóa và sáng tạo cho tất cả các công nhân đang chiếm ưu thế.

Một điều nữa. Việc đọc tệp CSV song song thậm chí có giúp ích không? Đĩa có phải là nút cổ chai hay là CPU? Nhiều câu trả lời được gọi là xếp hạng hàng đầu trên stackoverflow chứa trí tuệ dev phổ biến mà bạn chỉ cần một luồng để đọc tệp, tốt nhất bạn có thể làm, họ nói. Họ có chắc chắn không?

Hãy cùng tìm hiểu:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.256s
user    0m10.696s
sys 0m19.952s

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=1
11000000

real    0m17.380s
user    0m11.124s
sys 0m6.272s

Ồ vâng, vâng, đúng vậy. Đọc tệp song song hoạt động khá tốt. Vâng, bạn đi!

Thi thiên Trong trường hợp một số bạn muốn biết, điều gì sẽ xảy ra nếu thăng bằng 2 khi sử dụng một quy trình công nhân duy nhất? Chà, thật kinh khủng:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=2
11000000

real    1m37.077s
user    0m12.432s
sys 1m24.700s

Các phần chính của chương trình python fastread.py:

fileBytes = stat(fileName).st_size  # Read quickly from OS how many bytes are in a text file
startByte, endByte = PartitionDataToWorkers(workers=numProcesses, items=fileBytes, balanceFactor=balanceFactor)
p = Pool(numProcesses)
partialSum = p.starmap(ReadFileSegment, zip(startByte, endByte, repeat(fileName))) # startByte is already a list. fileName is made into a same-length list of duplicates values.
globalSum = sum(partialSum)
print(globalSum)


def ReadFileSegment(startByte, endByte, fileName, searchChar='\n'):  # counts number of searchChar appearing in the byte range
    with open(fileName, 'r') as f:
        f.seek(startByte-1)  # seek is initially at byte 0 and then moves forward the specified amount, so seek(5) points at the 6th byte.
        bytes = f.read(endByte - startByte + 1)
        cnt = len(re.findall(searchChar, bytes)) # findall with implicit compiling runs just as fast here as re.compile once + re.finditer many times.
    return cnt

Def cho PartitionDataToWorkers chỉ là mã tuần tự thông thường. Tôi đã để nó ra ngoài trong trường hợp người khác muốn thực hành một chút về lập trình song song. Tôi đã cho đi miễn phí những phần khó hơn: mã song song được thử nghiệm và hoạt động, vì lợi ích học tập của bạn.

Cảm ơn: Dự án H2O mã nguồn mở, do Arno và Cliff và nhân viên H2O cung cấp cho các video hướng dẫn và phần mềm tuyệt vời của họ, đã cung cấp cho tôi nguồn cảm hứng cho trình đọc bù byte song song hiệu suất cao python thuần như hình trên. H2O thực hiện đọc tệp song song bằng java, có thể gọi được bằng các chương trình python và R, và cực kỳ nhanh, nhanh hơn bất cứ thứ gì trên hành tinh khi đọc các tệp CSV lớn.


Các khối song song là những gì về cơ bản. Ngoài ra, tôi hy vọng SSD và Flash là những thiết bị lưu trữ tương thích duy nhất có kỹ thuật này. Quay HD không có khả năng tương thích.
Geoffrey Anderson

1
Làm thế nào bạn chiếm tài khoản cho các tập tin đĩa đệm hệ điều hành?
JamesThomasMoon1979

5

Katrielalex cung cấp cách để mở và đọc một tệp.

Tuy nhiên, cách thuật toán của bạn đi, nó đọc toàn bộ tệp cho từng dòng của tệp. Điều đó có nghĩa là tổng số lượng đọc một tệp - và tính toán khoảng cách Levenshtein - sẽ được thực hiện N * N nếu N là số lượng dòng trong tệp. Vì bạn lo ngại về kích thước tệp và không muốn giữ nó trong bộ nhớ, tôi lo ngại về thời gian chạy bậc hai . Thuật toán của bạn nằm trong lớp thuật toán O (n ^ 2) thường có thể được cải thiện với chuyên môn hóa.

Tôi nghi ngờ rằng bạn đã biết sự đánh đổi bộ nhớ so với thời gian chạy ở đây, nhưng có lẽ bạn sẽ muốn điều tra xem có cách nào hiệu quả để tính song song nhiều khoảng cách Levenshtein không. Nếu vậy sẽ rất thú vị để chia sẻ giải pháp của bạn ở đây.

Các tệp của bạn có bao nhiêu dòng và thuật toán của bạn phải chạy trên loại máy nào (năng lượng mem & cpu) và thời gian chạy được dung nạp là gì?

Mã sẽ trông như:

with f_outer as open(input_file, 'r'):
    for line_outer in f_outer:
        with f_inner as open(input_file, 'r'):
            for line_inner in f_inner:
                compute_distance(line_outer, line_inner)

Nhưng các câu hỏi là làm thế nào để bạn lưu trữ khoảng cách (ma trận?) Và bạn có thể đạt được lợi thế của việc chuẩn bị, ví dụ như outs_line để xử lý hoặc lưu trữ một số kết quả trung gian để sử dụng lại.


Quan điểm của tôi là bài đăng này không chứa câu trả lời cho câu hỏi, chỉ là một số câu hỏi khác! IMO nó sẽ phù hợp hơn như là một bình luận.
Katriel

1
@katriealex: Ơ. Lạ thật. Bạn đã thấy các vòng lặp lồng nhau, mở rộng câu trả lời của riêng bạn để phù hợp với câu hỏi thực tế? Tôi có thể xóa câu hỏi của mình ở đây khỏi câu trả lời của mình và vẫn có đủ nội dung để đảm bảo cung cấp câu hỏi này như một câu trả lời - mặc dù một phần -. Tôi cũng có thể chấp nhận nếu bạn chỉnh sửa câu trả lời của riêng bạn để bao gồm ví dụ về vòng lặp lồng nhau - câu hỏi được hỏi rõ ràng - và sau đó tôi có thể xóa câu trả lời của mình một cách vui vẻ. Nhưng một downvote là thứ tôi không nhận được.
cfi

Đủ công bằng; Tôi thực sự không thấy việc chứng minh các vòng lặp lồng nhau như một câu trả lời cho câu hỏi nhưng tôi đoán nó khá nhắm mục tiêu vào người mới bắt đầu. Downvote loại bỏ.
Katriel

3
#Using a text file for the example
with open("yourFile.txt","r") as f:
    text = f.readlines()
for line in text:
    print line
  • Mở tệp của bạn để đọc (r)
  • Đọc toàn bộ tập tin và lưu từng dòng vào danh sách (văn bản)
  • Lặp qua danh sách in từng dòng.

Ví dụ, nếu bạn muốn kiểm tra một dòng cụ thể có độ dài lớn hơn 10, hãy làm việc với những gì bạn đã có sẵn.

for line in text:
    if len(line) > 10:
        print line

1
Không tốt nhất cho câu hỏi này, nhưng mã này chủ yếu hữu ích trong trường hợp những gì bạn đang tìm kiếm. Đây là "slurping" (đọc toàn bộ tệp cùng một lúc). Đó là trường hợp của tôi và google đã đưa tôi đến đây. +1. Ngoài ra, đối với tính nguyên tử hoặc nếu bạn mất thời gian xử lý trong vòng lặp có thể kết thúc nhanh hơn để đọc toàn bộ tệp
ntg

1
Ngoài ra, đã cải thiện mã một chút: 1. không cần thiết phải đóng sau: ( docs.python.org/2/tutorial/inputoutput.html , tìm kiếm "Cách tốt nhất là sử dụng từ khóa với ...") 2 . văn bản có thể được xử lý sau khi đọc tệp (ouside of with loop ....)
ntg

2

Từ tài liệu python cho fileinput .input ():

Điều này lặp lại qua các dòng của tất cả các tệp được liệt kê trong sys.argv[1:], mặc định sys.stdinnếu danh sách trống

hơn nữa, định nghĩa của hàm là:

fileinput.FileInput([files[, inplace[, backup[, mode[, openhook]]]]])

đọc giữa các dòng, điều này cho tôi biết đó filescó thể là một danh sách để bạn có thể có một cái gì đó như:

for each_line in fileinput.input([input_file, input_file]):
  do_something(each_line)

Xem tại đây để biết thêm thông tin


2

Tôi thực sự khuyên bạn không nên sử dụng tải tập tin mặc định vì nó rất chậm. Bạn nên xem xét các hàm numpy và các hàm IOpro (ví dụ: numpy.loadtxt ()).

http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

https://store.cContuum.io/cshop/iopro/

Sau đó, bạn có thể chia hoạt động cặp của bạn thành khối:

import numpy as np
import math

lines_total = n    
similarity = np.zeros(n,n)
lines_per_chunk = m
n_chunks = math.ceil(float(n)/m)
for i in xrange(n_chunks):
    for j in xrange(n_chunks):
        chunk_i = (function of your choice to read lines i*lines_per_chunk to (i+1)*lines_per_chunk)
        chunk_j = (function of your choice to read lines j*lines_per_chunk to (j+1)*lines_per_chunk)
        similarity[i*lines_per_chunk:(i+1)*lines_per_chunk,
                   j*lines_per_chunk:(j+1)*lines_per_chunk] = fast_operation(chunk_i, chunk_j) 

Hầu như luôn luôn nhanh hơn nhiều để tải dữ liệu theo từng khối và sau đó thực hiện các thao tác ma trận trên nó hơn là thực hiện từng phần tử !!


0

Cần thường xuyên đọc một tập tin lớn từ vị trí đọc cuối cùng?

Tôi đã tạo một tập lệnh được sử dụng để cắt tệp Apache access.log nhiều lần trong ngày. Vì vậy, tôi cần phải đặt một con trỏ vị trí trên dòng cuối cùng được phân tích cú pháp trong lần thực hiện cuối cùng . Để kết thúc này, tôi đã sử dụng file.seek()file.seek() các phương thức cho phép lưu trữ con trỏ trong tệp.

Mã của tôi :

ENCODING = "utf8"
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))

# This file is used to store the last cursor position
cursor_position = os.path.join(CURRENT_FILE_DIR, "access_cursor_position.log")

# Log file with new lines
log_file_to_cut = os.path.join(CURRENT_FILE_DIR, "access.log")
cut_file = os.path.join(CURRENT_FILE_DIR, "cut_access", "cut.log")

# Set in from_line 
from_position = 0
try:
    with open(cursor_position, "r", encoding=ENCODING) as f:
        from_position = int(f.read())
except Exception as e:
    pass

# We read log_file_to_cut to put new lines in cut_file
with open(log_file_to_cut, "r", encoding=ENCODING) as f:
    with open(cut_file, "w", encoding=ENCODING) as fw:
        # We set cursor to the last position used (during last run of script)
        f.seek(from_position)
        for line in f:
            fw.write("%s" % (line))

    # We save the last position of cursor for next usage
    with open(cursor_position, "w", encoding=ENCODING) as fw:
        fw.write(str(f.tell()))

-2

Cách tốt nhất để đọc tệp lớn, từng dòng là sử dụng hàm liệt kê python

with open(file_name, "rU") as read_file:
    for i, row in enumerate(read_file, 1):
        #do something
        #i in line of that line
        #row containts all data of that line

3
Tại sao sử dụng liệt kê bất kỳ tốt hơn? Lợi ích duy nhất so với câu trả lời được chấp nhận là bạn có được một chỉ mục mà OP không cần và bạn đang làm cho mã ít đọc hơn.
fuyas
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.