Более быстрый способ изменить файл gzip xml (файл проекта Adobe Premiere Pro) в Python? - PullRequest
3 голосов
/ 09 января 2020

Это мой первый пост в сообществе stackoverflow после нескольких лет бездельничания и игры с python в свободное время. Я написал скрипт для изменения файлов Adobe Premiere Pro с целью понижения их до «Версия 1». Это позволяет пользователям открывать новые файлы проекта в более старых версиях программы.

Теперь, чтобы очистить, это было сделано раньше. На stackoverflow и форумах Adobe есть несколько человек, которые разместили вопросы и решения этой проблемы. Мой вопрос касается скорости / эффективности использования модуля python gzip и BeautifulSoup с парсером l xml для распаковки и изменения файла xml.

Вот код:

# Assume I've done all the imports like gzip, bs4, pathlib, sys, etc.
#
def downgrade(prproj_in):  # Main functionality of the program. Downgrades target prproj files.
"""
Shortened the docstring to save reading...
"""
new_version = '1'
root, ext = os.path.splitext(prproj_in)  # Checking if file extension is correct.
new_name = (root + '_DOWNGRADED' + '(v.' + str(new_version) + ').prproj')

try:
    if ext != '.prproj':
        print('Invalid filetype. Must have valid .prproj extension.')
        # If not a valid Adobe Premiere file, exit.
    elif os.path.exists(new_name):
        print('Output file already exists at this location. Please move or rename.')
    else:  # Otherwise... continue on to unzip and parse the xml file with BeautifulSoup.
        with tqdm(total=100) as pbar:  # Initialize progress bar.
            with gzip.open(prproj_in, 'rt') as f:  # Decompress project file and open...
                file_content = f.read()  # Put file contents into variable as string text
                soup = BeautifulSoup(file_content, 'xml')  # create soup object
                print('Current project version: ' +
                      soup.Project.find_next()['Version'])  # Printing current project version.
                soup.Project.find_next()['Version'] = new_version  # Change project version number to 1
                print('Downgraded project version to: ' +
                      str(soup.Project.find_next()['Version']))  # Print new current version.
                pbar.update(80)
                with gzip.open(new_name, 'wt') as f_out:
                    f_out.write(str(soup))  # Turn soup object to string for final writing to gzip file.
                    pbar.update(100)
                    print('Downgrade Complete. New file: ' + new_name)  # Change file extension.
except:
    exception = sys.exc_info()
    handle_exceptions(exception[0])

И вот начало распакованного файла .prproj с соответствующим атрибутом, который мне нужно изменить:

<?xml version="1.0" encoding="UTF-8" ?>
    <PremiereData Version="3">
        <Project ObjectRef="1"/>
        <Project ObjectID="1" ClassID="62ad66dd-0dcd-42da-a660-6d8fbde94876" Version="30">

Этот код отлично работает с файлами проекта, размер которых составляет всего несколько МБ (до распаковывается), но запускается до 10 минут, как только размер файла достигает 60, 70 или 80 МБ. В настоящее время я работаю над независимым документальным фильмом, в котором файлы моего проекта имеют размер более 100 МБ при сжатии и до 1,6 ГБ при распаковке. Я запускаю этот сценарий на iMa c Pro с 128 ГБ ОЗУ и процессором Xeon 3 ГГц.

Я протестировал пару других сценариев, плавающих на GitHub, и они, похоже, демонстрируют подобное поведение при работе с большими файлами проекта.

Хотелось бы услышать некоторые мысли о том, как справиться с этим. Спасибо!

Ответы [ 2 ]

1 голос
/ 16 января 2020

@ Alfe, спасибо за ваши мысли! Я смог решить проблему самостоятельно, переписав шаг парсинга xml с помощью регулярных выражений. До этого момента я не погружался в регулярные выражения, но обнаружил, что он работает на порядок быстрее, чем парсер Beautiful Soup.

Мой исправленный код на github: https://github.com/snorkem/prproj_downgrade/blob/master/prproj_downgrade.py

1 голос
/ 15 января 2020

Если я вас правильно понимаю (поправьте меня, если я ошибаюсь), вы хотите изменить деталь в начале файла gzipped.

Если это правильно, это не имеет большого значения, что несжатая версия файла - файл XML. Единственное, что имеет значение, это то, что вы хотите немного изменить начало сжатого файла.

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

В вашем случае, боюсь, вам придется распаковать весь файл, изменить его и снова сжать. Чтобы избежать этого, вам необходимо изменить архитектуру вашего проекта так, чтобы начало и остальная часть файла хранились отдельно друг от друга, например, в двух разных файлах. Затем используемому программному обеспечению потребуется сшить два файла вместе, когда потребуется информация * 1013. *

Если вы выбрали go для первого варианта и распаковать → изменить → повторно сжать файл, то вы можете сделать это с помощью трубопровода, который позволяет сделать это за один шаг. Не стесняйтесь задавать еще один вопрос по этой теме c (и ссылку из комментария здесь на новый вопрос), если вам нужен еще совет.

...