CSV'yi python'da belleğe yüklemeden bir CSV'ye başlık satırı eklemenin bir yolu var mı? Bir başlık eklemek istediğim 18GB'lık bir CSV var ve gördüğüm tüm yöntemler CSV'yi belleğe yüklemeyi gerektiriyor.CSV yüklenemedi başlık CSV yüklenemedi
cevap
Sadece gerçeği kullandıkları satırlarda csv
modül yinelediğinden asla writerows
çok iyi bir hız sağlamak kullanarak belleğe
import csv
with open("huge_csv.csv") as fr, open("huge_output.csv","w",newline='') as fw:
cr = csv.reader(fr)
cw = csv.writer(fw)
cw.writerow(["title1","title2","title3"])
cw.writerows(cr)
tüm dosyayı yükler böylece. Bellek buradan kurtuldu. Her şey hattan yapılır. Veriler doğru bir şekilde işlendiğinden, ayırıcıyı ve/veya çıktı dosyasındaki alıntıları bile değiştirebilirsiniz.
Tüm dosyayı yeniden yazmanız gerekecektir. En basit
echo 'col1, col2, col2,... ' > out.csv
cat in.csv >> out.csv
Python tabanlı çözümler çok daha yüksek düzeylerde çalışacak ve çok yavaş olacaktır Python kullanmak değildir. 18GB, hepsinden sonra çok veri. En hızlı olacak işletim sistemi işlevselliği ile çalışmak daha iyidir.
Python'dan ayrılmak istemiyorsanız, bunu bir 'subprocess.call()' çağrısında her zaman yapabilirsiniz. Hatta Python'daki ilk satırın yazısını da @ maximilian-peters'ın cevabı gibi yapın. –
Bu aslında en hızlı çözümdür, diğer cevaptaki referans noktasına bakın. –
Karşılaştırma yapmak için zaman ayırdığınız için @MaximilianPeters teşekkürler – e4c5
Burada 10^6 satır ve 10 sütun (n = 50) olan bir ~ 200 MB CSV dosyası için önerilen üç çözümün bir karşılaştırması. Bu oran, daha büyük ve daha küçük dosyalar için yaklaşık aynı kalır (10 MB - 8 GB).
cp: shutil: yerleşik
cp
işlevini kullanarak 1:10:55
yani Python'un csv
modülü kullanarak yaklaşık olarak 55 kat daha hızlı olduğu csv_reader.
Bilgisayar:
- düzenli HDD
- Python 3.5.2 64 bit
- Ubuntu 16.04
- i7-3770
import csv
import random
import shutil
import time
import subprocess
rows = 1 * 10**3
cols = 10
repeats = 50
shell_script = '/tmp/csv.sh'
input_csv = '/tmp/temp.csv'
output_csv = '/tmp/huge_output.csv'
col_titles = ['titles_' + str(i) for i in range(cols)]
with open(shell_script, 'w') as f:
f.write("#!/bin/bash\necho '{0}' > {1}\ncat {2} >> {1}".format(','.join(col_titles), output_csv, input_csv))
with open(shell_script, 'w') as f:
f.write("echo '{0}' > {1}\ncat {2} >> {1}".format(','.join(col_titles), output_csv, input_csv))
subprocess.call(['chmod', '+x', shell_script])
run_times = dict([
('csv_writer', list()),
('external', list()),
('shutil', list())
])
def random_csv():
with open(input_csv, 'w') as csvfile:
csv_writer = csv.writer(csvfile, delimiter=',')
for i in range(rows):
csv_writer.writerow([str(random.random()) for i in range(cols)])
with open(output_csv, 'w'):
pass
for r in range(repeats):
random_csv()
#http://stackoverflow.com/a/41982368/2776376
start_time = time.time()
with open(input_csv) as fr, open(output_csv, "w", newline='') as fw:
cr = csv.reader(fr)
cw = csv.writer(fw)
cw.writerow(col_titles)
cw.writerows(cr)
run_times['csv_writer'].append(time.time() - start_time)
random_csv()
#http://stackoverflow.com/a/41982383/2776376
start_time = time.time()
subprocess.call(['bash', shell_script])
run_times['external'].append(time.time() - start_time)
random_csv()
#http://stackoverflow.com/a/41982383/2776376
start_time = time.time()
with open('header.txt', 'w') as header_file:
header_file.write(','.join(col_titles))
with open(output_csv, 'w') as new_file:
with open('header.txt', 'r') as header_file, open(input_csv, 'r') as main_file:
shutil.copyfileobj(header_file, new_file)
shutil.copyfileobj(main_file, new_file)
run_times['shutil'].append(time.time() - start_time)
print('#'*20)
for key in run_times:
print('{0}: {1:.2f} seconds'.format(key, run_times[key][-1]))
print('#'*20)
print('Averages')
for key in run_times:
print('{0}: {1:.2f} seconds'.format(key, sum(run_times[key])/len(run_times[key])))
gerçekten Python bunu yapmak istiyorsan, önce başlık dosyası oluşturmak ve sonra shutil.copyfileobj
üzerinden 2 dosyasıyla birleştirebilir.
import shutil
with open('header.txt', 'w') as header_file:
header_file.write('col1;col2;col3')
with open('new_file.csv', 'w') as new_file:
with open('header.txt', 'r') as header_file, open('main.csv', 'r') as main_file:
shutil.copyfileobj(header_file, new_file)
shutil.copyfileobj(main_file, new_file)
DictWriter'ın writeheader yöntemini denediniz mi? (https://docs.python.org/3/library/csv.html) Tam cevabı bilmiyorum, sadece bir fikir: Eğer dosyayı 'a' ile açarsanız ve writeheader'ı kullanmaya çalışırsanız çalışıyor mu? Eğer yanlış bir şey varsa, orijinal dosyanın bir kopyasını deneyerek bunu yapmak iyi olurdu. – Kroy
3 yöntemin hız karşılaştırması için güncellenmiş cevaba bakın. –