Преобразование docx в pdf с помощью чистого python (на linux, без libreoffice)

Я столкнулся с проблемой, пытаясь разработать веб-приложение, часть которого преобразует загруженные файлы docx в файлы pdf (после некоторой обработки). С python-docx и другими методами мне не требуется машина Windows с установленным word или даже libreoffice на linux для большей части обработки (мой веб-сервер pythonanywhere - linux, но без libreoffice и без разрешений sudo или apt install). Но для преобразования в pdf, похоже, требуется один из них. Изучая вопросы здесь и в других местах, вот что у меня есть на данный момент:

import subprocess

try:
    from comtypes import client
except ImportError:
    client = None

def doc2pdf(doc):
    """
    convert a doc/docx document to pdf format
    :param doc: path to document
    """
    doc = os.path.abspath(doc) # bugfix - searching files in windows/system32
    if client is None:
        return doc2pdf_linux(doc)
    name, ext = os.path.splitext(doc)
    try:
        word = client.CreateObject('Word.Application')
        worddoc = word.Documents.Open(doc)
        worddoc.SaveAs(name + '.pdf', FileFormat=17)
    except Exception:
        raise
    finally:
        worddoc.Close()
        word.Quit()


def doc2pdf_linux(doc):
    """
    convert a doc/docx document to pdf format (linux only, requires libreoffice)
    :param doc: path to document
    """
    cmd = 'libreoffice --convert-to pdf'.split() + [doc]
    p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    p.wait(timeout=10)
    stdout, stderr = p.communicate()
    if stderr:
        raise subprocess.SubprocessError(stderr)

Как видите, для одного метода требуется comtypes, для другого - libreoffice в качестве подпроцесса. Есть ли какое-нибудь решение, кроме перехода на более сложный хостинг-сервер?

Python-docx не требует Word (или Windows), потому что практически всю работу он выполняет внутри своего исходного кода. («Практически все», за исключением нескольких внешних стандартных модулей, таких как XML, файлы ZIP и обработка изображений.) Поскольку Python является полным по Тьюрингу языком, вы можете сделать то же самое для создания PDF из ничего без внешнего программного обеспечения. . Прочтите официальные спецификации от начала до конца, и вы поймете, почему гораздо проще использовать внешнюю программу.

Jongware 22.06.2018 15:42

@ usr2564301 Конечно проще, но для меня это не вариант без переключения серверов

Ofer Sadan 23.06.2018 00:01

Затем найдите чистую реализацию Python для создания PDF-файлов (рекомендовать одну - это противоречие рекомендациям по переполнению стека, но, конечно, вы можете использовать поисковую систему и найти ту, которая подходит для ваших целей и уровня программирования), или сверните свою собственную. Но будьте осторожны, есть веские причины, по которым «все» используют внешние утилиты - прочтите вышеупомянутые спецификации, чтобы понять, почему.

Jongware 23.06.2018 00:09

почему бы не использовать api, запускаемый с помощью python, например. convertapi.com/docx-to-pdf? Также проверьте этот вопрос stackoverflow.com/questions/3815983/…

Zephro 29.06.2018 15:57

Вместо этого попробуйте pandoc.

pylang 08.07.2018 21:37
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
18
5
24 136
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Страницы справки PythonAnywhere предлагают информацию по работе с файлами PDF здесь: https://help.pythonanywhere.com/pages/PDF

Описание: PythonAnywhere имеет несколько установленных пакетов Python для работы с PDF, и один из них может делать то, что вы хотите. Однако мне кажется проще всего перейти на abiword. Команда оболочки abiword --to=pdf filetoconvert.docx преобразует файл docx в PDF и создаст файл с именем filetoconvert.pdf в том же каталоге, что и docx. Обратите внимание, что эта команда выведет сообщение об ошибке в стандартный поток ошибок с жалобой на XDG_RUNTIME_DIR (или, по крайней мере, у меня), но она по-прежнему работает, и сообщение об ошибке можно игнорировать.

Мне нужно будет провести несколько тестов, чтобы увидеть, работает ли он, не испортив файлы, но это именно тот ответ, который я хотел услышать :) сообщит о результатах

Ofer Sadan 01.07.2018 14:00

У меня это тоже работает. Он создает файл pdf (с тем же именем файла), но я также получил ошибку XDG_RUNTIME_DIR. Чтобы обуздать эту ошибку, я использовал export XDG_RUNTIME_DIR=/tmp/ в консоли bash, и со второй попытки ошибка исчезла. Наконец, чтобы проверить, было ли преобразование успешным, я загрузил файл pdf из Pythonanywhere на свой компьютер локально и открыл файл, чтобы увидеть его содержимое. Весь контент отображается успешно.

amanb 02.07.2018 13:41

Отчетность: это работает достаточно хорошо (некоторые проблемы с языками с письмом справа налево), но на данный момент это лучшее решение для меня (в конце концов, я, вероятно, перейду на облако Google). Спасибо!

Ofer Sadan 03.07.2018 10:01

С веб-сайта Abiword: «Обратите внимание, пользователи Windows: из-за отсутствия разработчиков Windows в проекте больше нет версии, доступной для загрузки».

Thom Ives 06.10.2019 18:45

@ThomIves Хотя это может быть правдой, речь идет об использовании Linux через PythonAnywhere, поэтому версии Windows здесь не актуальны.

jcgoble3 06.10.2019 18:47

@ jcgoble3 Согласен, и, хотя я бы предпочел все делать в Linux, иногда мне приходится работать в Windows, поэтому я решил сообщить другим, кто ищет общие решения.

Thom Ives 06.10.2019 20:11

Большое спасибо! Эта подсказка с abiword изумительна!

Pedroski 04.04.2020 01:02

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

в любом случае, после того, как вы установили libreoffice, вот код для этого.

from subprocess import  Popen
LIBRE_OFFICE = r"C:\Program Files\LibreOffice\program\soffice.exe"

def convert_to_pdf(input_docx, out_folder):
    p = Popen([LIBRE_OFFICE, '--headless', '--convert-to', 'pdf', '--outdir',
               out_folder, input_docx])
    print([LIBRE_OFFICE, '--convert-to', 'pdf', input_docx])
    p.communicate()


sample_doc = 'file.docx'
out_folder = 'some_folder'
convert_to_pdf(sample_doc, out_folder)

похоже, это не работает параллельно. Я создаю 10 экземпляров Popen для преобразования 10 файлов docx, но получаю только 5 pdf и без каких-либо ошибок.

Z fp 20.03.2021 08:06

интересно, я сделал это некоторое время назад, но, может быть, выложите свой код?

dfresh22 20.03.2021 08:13

Я разместил вопрос со своими кодами: stackoverflow.com/questions/66719566/… @ dfresh22

Z fp 20.03.2021 09:27

Другие вопросы по теме