日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python 导入数据对不齐_[Python] 大文件数据读取分析

發布時間:2024/7/19 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 导入数据对不齐_[Python] 大文件数据读取分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先我們可以確定的是不能用read()與readlines()函數;

因為如果將這兩個函數均將數據全部讀入內存,會造成內存不足的情況。

針對數據按行劃分的文件

以計算行數為例,首先針對幾種不同的方法來作比較:

1、使用for遍歷的方法,比較美觀,網上搜索到八有十九是讓你這樣做,盡管已經很快了但還不是最快的

start = time.time()

with open(dataPath, 'r') as f:

count = 0

for line in f:

count += 1

print(count)

print(time.time() - start)

輸出:

5000

0.09386205673217773

2、使用readline()模擬遍歷,發現其實結果和第一種差不多

start = time.time()

with open(dataPath, 'r') as f:

line = f.readline()

count = 1

while line:

count += 1

line = f.readline()

print(count - 1)

print(time.time() - start)

輸出:

5000

0.09433221817016602

3、對比readlines()直接去訪問,結果卻更慢了!

start = time.time()

with open(dataPath, 'r') as f:

count = 0

for line in f.readlines():

count += 1

print(count)

print(time.time() - start)

輸出:

5000

0.12223696708679199

4、不斷去檢測文件指針位置,有的時候我們可能需要讀到特定的文件位置就停下;就會發現tell()十分耗時!

start = time.time()

with open(dataPath, 'r') as f:

count = 0

while f.tell() < datasize:

f.readline()

count += 1;

print(count)

print(time.time() - start)

輸出:

5000

0.29171299934387207

5、使用mmap的方法,mmap是一種虛擬內存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間,實現文件磁盤地址和進程虛擬地址空間中一段虛擬地址的一一對映關系。通過建立一個文件的內存映射將使用操作系統虛擬內存來直接訪問文件系統上的數據,而不是使用常規的I/O函數訪問數據。內存映射通常可以提供I/O性能,因為使用內存映射是,不需要對每個訪問都建立一個單獨的系統調用,也不需要在緩沖區之間復制數據;實際上,內核和用戶應用都能直接訪問內存,是目前測到最快的方法。

import mmap

start = time.time()

with open(dataPath, "r") as f:

# memory-map the file, size 0 means whole file

map = mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ)

count = 0

while map.readline():

count += 1

print(count)

map.close()

print(time.time() - start)

輸出:

5000

0.023865938186645508

6、可以不按行讀取,而是按塊讀取,然后分析\n的個數,但這只針對計算行數而論可行,但我們真正想要的是按行讀取數據,所以這里只給出實現方法,不進行對比。

with open(r"d:\lines_test.txt",'rb') as f:

count = 0

while True:

buffer = f.read(1024 * 8192)

if not buffer:

break

count += buffer.count('\n')

print count

考慮MPI的情況

當文件很大的時候,任務又需要并行化的話,我們可以將文件拆分成多段去處理,例如對于4核的電腦,可以讓4條進程分別去處理文件不同的部分,每條進程讀四分之一的數據。但這時候要考慮到,分割點不一定剛好是換行符的情況,所以我們可以考慮從分割點下一個換行符開始搜索,分割點第一個換行符之前的交給前一個進程去處理,處理方法如圖:

實現類似:

from mpi4py import MPI

import platform

import sys

import io

import os

import mmap

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

comm = MPI.COMM_WORLD

comm_size = comm.size

comm_rank = comm.rank

with open(filePath, 'r', encoding='utf-8') as f:

# Set the file pointer to the beginning of a line after blockSize * rank

# Use mmap to run faster

map = mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ)

map.seek(comm_rank * blockSize)

if comm_rank != 0:

map.readline()

# Each process handle about blocksize lines.

blockEnd = (comm_rank + 1) * blockSize

# Use index here to avoid using twice map.tell()

index = map.tell()

while index <= blockEnd and index < dataSize:

# line = map.readline().translate(None, b'\x00').decode()

line = map.readline().decode('utf-8')

index = map.tell()

try:

dosomething(line)

except Exception as err:

print(err)

continue

如果不用mmap.tell()改用f.tell()的話,效率其差,一開始我遇到這種情況的時候是想著自己不斷去加len(line)去自己計算文件指針的位置的。但又發現一個問題,file.readline()會幫你去除部分字符,例如\r\n只會保留\n,而mmap.readline()則不會,而且試過表示很難,總是和f.tell()對不齊。

數據按特殊符號劃分

考慮到可能數據劃分點不是\n, 我們可以這樣讀取:

def rows(f, chunksize=1024, sep='|'):

"""

Read a file where the row separator is '|' lazily.

Usage:

>>> with open('big.csv') as f:

>>>? ? for r in rows(f):

>>>? ? ? ? process(row)

"""

curr_row = ''

while True:

chunk = f.read(chunksize)

if chunk == '': # End of file

yield curr_row

break

while True:

i = chunk.find(sep)

if i == -1:

break

yield curr_row + chunk[:i]

curr_row = ''

chunk = chunk[i+1:]

curr_row += chunk

數據無特定劃分方式

一種方法是用yield:

def read_in_chunks(file_object, chunk_size=1024):

"""Lazy function (generator) to read a file piece by piece.

Default chunk size: 1k."""

while True:

data = file_object.read(chunk_size)

if not data:

break

yield data

with open('really_big_file.dat') as f:

for piece in read_in_chunks(f):

process_data(piece)

另外一種方法是用iter和一個helper function:

f = open('really_big_file.dat')

def read1k():

return f.read(1024)

for piece in iter(read1k, ''):

process_data(piece)

總結

以上是生活随笔為你收集整理的python 导入数据对不齐_[Python] 大文件数据读取分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。