Python3 разбивает большой файл разделителем на маленькие файлы (не размер, строки) - PullRequest
1 голос
/ 09 марта 2019

Новичок здесь.Конечная миссия - научиться брать два больших файла yaml и разбивать их на несколько сотен маленьких файлов.Я еще не понял, как использовать ID # в качестве имени файла, так что по одному.

Первое: разбить большие файлы на множество.Вот небольшой кусочек моего файла тестовых данных test-file.yml.Каждый пост имеет отдельный разделитель в строке:

-
    ID: 627
    more_post_meta_data_and_content
-
    ID: 628

А вот мой код, который не работает.Пока я не понимаю, почему:

with open('test-file.yml', 'r') as myfile:
    start = 0
    cntr = 1
    holding = ''
    for i in myfile.read().split('\n'):
        if (i == '-\n'):
            if start==1:
                with open(str(cntr) + '.md','w') as opfile:
                    opfile.write(op)
                    opfile.close()
                    holding=''
                    cntr += 1
            else:
                start=1
        else:
            if holding =='':
                holding = i
            else:
                holding = holding + '\n' + i
    myfile.close()

Все советы, предложения, указатели приветствуются.Спасибо.

Ответы [ 3 ]

0 голосов
/ 09 марта 2019

Считывание всего файла в память и последующее разделение областей памяти очень неэффективно, если входные файлы большие.Попробуйте вместо этого:

with open('test-file.yml', 'r') as myfile:
    opfile = None
    cntr = 1
    for line in myfile:
        if line == '-\n':
            if opfile is not None:
                opfile.close()
            opfile = open('{0}.md'.format(cntr),'w')
            cntr += 1
        opfile.write(line)
    opfile.close()

Обратите внимание, что вы не close открываете вещи в with диспетчере контекста;Сама цель менеджера контекста - позаботиться об этом за вас.

0 голосов
/ 09 марта 2019

Когда вы работаете с with context над открытым файлом, with автоматически позаботится о его закрытии, когда вы выйдете из этого блока.Поэтому вам не нужно ни file.close().

Существует функция с именем readlines, которая выводит генератор, который читает строку из открытого файла по одной строке за раз.Это будет работать намного эффективнее, чем read(), за которым следует split().Думаю об этом.Вы загружаете массивный файл в память, а затем просите CPU разделить этот огромный текст на \n символ.Не очень эффективно.

Вы написали opfile.write(op).Где это op определено?Разве вы не хотите писать содержимое в holding, которое вы определили?

Попробуйте выполнить следующее.

with open('test.data', 'r') as myfile:
    counter = 1
    content = ""
    start = True

    for line in myfile.readlines():
        if line == "-\n" and not start:
            with open(str(counter) + '.md', 'w') as opfile:
                opfile.write(content)

            content = ""
            counter += 1
        else:
            if not start:
                content += line

        start = False

    # write the last file if test-file.yml doesn't end with a dash
    if content != "":
        with open(str(counter) + '.md', 'w') as opfile:
            opfile.write(content)
0 голосов
/ 09 марта 2019

Как новичок, на первый взгляд вы пытаетесь записать необъявленную переменную op в свой вывод. Вы были почти на месте, просто нужно перебрать ваш opfile и написать содержимое:

    with open('test-file.yml', 'r') as myfile:
        start = 0
        cntr = 1
        holding = ''
        for i in myfile.read().split('\n'):
            if (i == '-\n'):
                if start==1:
                    with open(str(cntr) + '.md','w') as opfile:
                        for line in opfile:
                            op = line
                            opfile.write(op)
                            opfile.close()
                            holding=''
                            cntr += 1
                else:
                    start=1
            else:
                if holding =='':
                    holding = i
                else:
                    holding = holding + '\n' + i
        myfile.close()

Надеюсь, это поможет!

...