2016-05-11 4 views
4

Я пытаюсь извлечь 10'000 первых строк из файла bz2.Чтение первых строк файлов bz2 в python

import bz2  
    file = "file.bz2" 
    file_10000 = "file.txt" 

    output_file = codecs.open(file_10000,'w+','utf-8') 

    source_file = bz2.open(file, "r") 
    count = 0 
    for line in source_file: 
     count += 1 
     if count < 10000: 
      output_file.writerow(line) 

Но я получаю сообщение об ошибке. Объект '' module 'не имеет атрибута' open '". У тебя есть идеи? Или, может быть, я мог бы сохранить 10'000 первых строк в txt-файле каким-то другим способом? Я нахожусь в Windows.

+0

Какая версия Python вы используете? 'bz2.open' находится в python 3, а не python 2. Вместо этого попробуйте' bz2.BZ2File'. – tdelaney

+0

У меня есть python 2.7, с 'bz2.BZ2File' Я получаю такое же сообщение об ошибке – student

+0

Это невозможно. Как вы используете BZ2File и какую ошибку вы получаете? – tjollans

ответ

4

Вот полный рабочий пример, который включает в себя запись и чтение тестового файла, который намного меньше, чем ваши 10000 строк. Приятно иметь рабочие примеры в вопросах, чтобы мы могли легко протестировать.

import bz2 
import itertools 
import codecs 

file = "file.bz2" 
file_10000 = "file.txt" 

# write test file with 9 lines 
with bz2.BZ2File(file, "w") as fp: 
    fp.write('\n'.join('123456789')) 

# the original script using BZ2File ... and 3 lines for test 
# ...and fixing bugs: 
#  1) it only writes 9999 instead of 10000 
#  2) files don't do writerow 
#  3) close the files 

output_file = codecs.open(file_10000,'w+','utf-8') 

source_file = bz2.BZ2File(file, "r") 
count = 0 
for line in source_file: 
    count += 1 
    if count <= 3: 
     output_file.write(line) 
source_file.close() 
output_file.close() 

# show what you got 
print('---- Test 1 ----') 
print(repr(open(file_10000).read())) 

Более эффективный способ сделать это, чтобы вырваться из петли for после прочтения строки, которые вы хотите. Вы можете даже использовать итераторы для тонкой до кода, как так:

# a faster way to read first 3 lines 
with bz2.BZ2File(file) as source_file,\ 
     codecs.open(file_10000,'w+','utf-8') as output_file: 
    output_file.writelines(itertools.islice(source_file, 3)) 

# show what you got 
print('---- Test 2 ----') 
print(repr(open(file_10000).read())) 
3

Это, безусловно, более простой способ сделать это, чем другой ответ, но это было бы простой способ сделать это в обоих python2/3. Кроме того, это будет короткое замыкание, если у вас нет> = 10 000 строк.

from bz2 import BZ2File as bzopen 

# writing to a file 
with bzopen("file.bz2", "w") as bzfout: 
    for i in range(123456): 
     bzfout.write(b"%i\n" % i) 

# reading a bz2 archive 
with bzopen("file.bz2", "r") as bzfin: 
    """ Handle lines here """ 
    lines = [] 
    for i, line in enumerate(bzfin): 
     if i == 10000: break 
     lines.append(line.rstrip()) 

print(lines) 
+0

Так как у python 3 также есть 'BZ2File', я не вижу необходимости делать двойной импорт. – tdelaney

+0

'open' обернут объектом' io.TextIOWrapper', поэтому у вас больше гибкости с кодировками и т. Д. Я предпочитаю его в BZ2-файле для начала. – Goodies

+0

_ «Это определенно более простой способ сделать это, чем другой ответ», - вы имеете в виду мой ответ? Как это проще? Он извлекает все 10000 строк в память и вообще не записывает выходной файл. – tdelaney

1

Просто еще одна вариация.

import bz2 

myfile = 'c:\\users\\rafporti\\documents\\random.txt.bz2' 
newfile = 'c:\\users\\rafporti\\documents\\random_10000.txt' 

stream = bz2.BZ2File(myfile) 
with open(newfile, 'w') as f: 
    for i in range(1,10000): 
    f.write(stream.readline()) 
0

Это работает для меня:

sudo apt-get install python-dev 
sudo pip install backports.lzma 
Смежные вопросы