Wand TypeError

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Huhu und zwar habe ich ein Problem, ich möchte einen neuen Ordner erstellen (was auch klappt) und eine pdf-Datei in Bilder splitten (pdf-Datei hat Rechte chmod -v 777 kickoff18.pdf) allerdings bekomme ich ständig eine Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "main.py", line 5, in <module>
    presentation.convert("/home/felix/Schreibtisch/PythonTest/", "kickoff18.pdf", "/home/felix/Schreibtisch/PythonTest/", "neuerOrdner")
  File "/home/felix/Schreibtisch/PythonTest/model/presentation.py", line 16, in convert
    pdf = wa(filename = path + filename, resolution=300)
  File "/usr/lib/python2.7/dist-packages/wand/image.py", line 2744, in __init__
    self.read(filename=filename, resolution=resolution)
  File "/usr/lib/python2.7/dist-packages/wand/image.py", line 2822, in read
    self.raise_exception()
  File "/usr/lib/python2.7/dist-packages/wand/resource.py", line 222, in raise_exception
    raise e
wand.exceptions.PolicyError: not authorized `/home/felix/Schreibtisch/PythonTest/kickoff18.pdf' @ error/constitute.c/ReadImage/412
Exception TypeError: TypeError("object of type 'NoneType' has no len()",) in <bound method Image.__del__ of <wand.image.Image: (empty)>> ignored
presentation:

Code: Alles auswählen

from wand.image import Image as wa
import os, os.path


class Presentation:
    """Class that divides a PDF into individual images and converts them to jpg"""

    def __init__(self):
        """Constructor of the class"""
        pass

    def convert(self, path, filename, folder_path, folder_name):
        """a method that takes a path and a PDF file, converts them to JPG, and then saves the individual images"""
        folder = folder_path + folder_name
        os.makedirs(folder)
        pdf = wa(filename = path + filename, resolution=300)
        pdf_images = pdf.convert("jpeg")
        print("Bis hier")
        os.chdir(folder)
        page_number = 1
        for img in pdf_images.sequence:
            page = wa(image=img)
            page.save(filename=str(page_number) + ".jpg")
            page_number += 1
main:

Code: Alles auswählen

from model.presentation import Presentation

if __name__ == "__main__": 
    presentation = Presentation()
    presentation.convert("/home/felix/Schreibtisch/PythonTest/", "kickoff18.pdf", "/home/felix/Schreibtisch/PythonTest/", "neuerOrdner")
    print("Run")
Kurz noch zu dem Problem allgemein:
Es soll möglich sein einen neuen Ordner anzulegen, in welchem die Bilder der gesplitteten PDF liegen welche dann wiederrum ausgelesen werden sollen ob in der unteren rechten Ecke genug "weißer" Platz vorhanden ist um ein Video einzufügen, falls das der Fall ist soll das Video eingeblendet werden ansonsten soll das Bild der PDF unverändert dargestellt werden.
Vielen Dank im Vorraus :)
MfG Felix
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Klasse ist nicht sinnvoll, convert ist eine einfache Funktion.
Pfade setzt man mit os.path.join zusammen nicht mit +.
wa ist eine unlesbare Abkürzung von Image, warum nicht Image lassen?
os.chdir darf in einem Normalen Programm nicht vorkommen, weil es einen globalen Zustand ändert, der an anderen Stellen zu Fehlern führen kann.

Code: Alles auswählen

import os
from wand.image import Image

def convert(path, filename, folder_path, folder_name):
    """a method that takes a path and a PDF file,
    converts them to JPG, and then saves the individual images"""
    folder = os.path.join(folder_path, folder_name)
    os.makedirs(folder)
    pdf = Image(filename = os.path.join(path, filename), resolution=300)
    pdf_images = pdf.convert("jpeg")
    print("Bis hier")
    for page_number, img in enumerate(pdf_images.sequence, 1):
        page = Image(image=img)
        page.save(filename="{}.jpg".format(page_number))

if __name__ == "__main__": 
    convert("/home/felix/Schreibtisch/PythonTest/", "kickoff18.pdf", "/home/felix/Schreibtisch/PythonTest/", "neuerOrdner")
    print("Run")
Hier scheint jemand das selbe Problem gehabt zu haben.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Huhu Sirius3,
erstmal vielen Dank für deine Antwort hättest du vlt. noch weitere Vorschläge/Anregungen wie ich an den Rest des Problems gehen sollte ich hatte dort an opencv gedacht !?
Und was ich nicht so ganz verstehe ist dieses in enumerate weil woher weiß Python das diese "Bilder" Aufzählungen sein können ? (final static)
Mfg Felix
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Darüber haben wir in deinem andren Thread doch diskutiert. Was von den dort vorgeschlagenen Ansätzen hast du probiert? Was hast du nicht verstanden?
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

@Sirius3
Es funktioniert leider immer noch nicht :(
Getestet mit 2.7 und 3.6:

Code: Alles auswählen

Traceback (most recent call last):
  File "main.py", line 5, in <module>
    presentation.convert("/home/felix/Schreibtisch/PythonTest/", "kickoff18.pdf", "/home/felix/Schreibtisch/PythonTest/", "neuerOrdner")
  File "/home/felix/Schreibtisch/PythonTest/model/presentation.py", line 16, in convert
    pdf = Image(filename= os.path.join(path, filename), resolution=300)
  File "/usr/lib/python2.7/dist-packages/wand/image.py", line 2744, in __init__
    self.read(filename=filename, resolution=resolution)
  File "/usr/lib/python2.7/dist-packages/wand/image.py", line 2822, in read
    self.raise_exception()
  File "/usr/lib/python2.7/dist-packages/wand/resource.py", line 222, in raise_exception
    raise e
wand.exceptions.PolicyError: not authorized `/home/felix/Schreibtisch/PythonTest/kickoff18.pdf' @ error/constitute.c/ReadImage/412
Exception TypeError: TypeError("object of type 'NoneType' has no len()",) in <bound method Image.__del__ of <wand.image.Image: (empty)>> ignored

Code: Alles auswählen

Traceback (most recent call last):
  File "main.py", line 5, in <module>
    presentation.convert("/home/felix/Schreibtisch/PythonTest/", "kickoff18.pdf", "/home/felix/Schreibtisch/PythonTest/", "neuerOrdner")
  File "/home/felix/Schreibtisch/PythonTest/model/presentation.py", line 16, in convert
    pdf = Image(filename= os.path.join(path, filename), resolution=300)
  File "/home/felix/.local/lib/python3.6/site-packages/wand/image.py", line 4708, in __init__
    self.read(filename=filename, resolution=resolution)
  File "/home/felix/.local/lib/python3.6/site-packages/wand/image.py", line 5002, in read
    self.raise_exception()
  File "/home/felix/.local/lib/python3.6/site-packages/wand/resource.py", line 222, in raise_exception
    raise e
wand.exceptions.PolicyError: not authorized `/home/felix/Schreibtisch/PythonTest/kickoff18.pdf' @ error/constitute.c/ReadImage/412
Ideen woran das liegen kann ?
btw: diese Methode muss sich in einer Klasse befinden, da Sie in einem größeren Projekt eingearbeitet wird
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Was hast Du denn geändert? Wie sieht die policy-Datei bei Dir aus?
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei man sich das ändern der Policy-Datei IMHO gut überlegen sollte. Das wurde ja nicht zum Spass gemacht, sondern um eine Sicherheitslücke zu schliessen, die man damit wieder öffnet.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Also wenn ich die Policy-Datei ändere funktioniert es, allerdings ist das nicht Sinn und Zweck, da ich nicht vom "Kunden" erwarten kann die policy.xml zu ändern.
Ich hatte mir kurz die Pillow Doku angesehen allerdings bin ich noch nicht ganz schlau daraus geworden ob es damit auch möglich wäre.
Vlt. hat ja jemand einen Vorschlag wie es relativ simpel ohne wand und Imagick umzusetzen wäre !?
Ich muss dazu sagen das ich allgemein bei Python Librarys in der Anwendungsentwicklung noch ziemlich unerfahren bin, da ich bis auf ein paar einfache Skripte in Python für größere Projekte doch eher Java bevorzuge.
MfG Felix
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn man deinen Fehler googelt finden sich Alternativen wie pdf2ppm. Schlussendlich Schein ghostscript das Problem zu sein, und das kannst du ggf direkt benutzen in einer Version die repariert ist.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Felix92 hat geschrieben: Freitag 15. März 2019, 20:25 Und was ich nicht so ganz verstehe ist dieses in enumerate weil woher weiß Python das diese "Bilder" Aufzählungen sein können ? (final static)
enumerate() zählt einfach die Anzahl an Objekten mit und liefert dies als Tupel (Zählerstand, Objekt) zurück. Das spart halt zwei Zeilen bzw lagert das eigentliche Zählen aus. Um es sinnvoll nutzen zu können, muss man das sogenannte Tuple Unpacking in Python verstanden haben.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

@__deets__ wenn ich das richtig verstanden habe sollte es also reichen die neuste Version von ghostscript zu installieren ? Oder könnte man den Fix für die policy vlt. in einer Methode mit einbinden, so dass der Kunde es nicht selbst ändern muss ?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ersteres musst du ausprobieren. Letzteres kann ich mir nicht vorstellen. Welchen Sinn hätte eine policy, wenn sie so einfach zu umgehen wäre? Dann braucht man sie erst gar nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Felix92: Wenn da keine „rolling release“ Linux-Distribiution verwendet wird, kann man ja nicht so einfach eine neuere Ghostscript-Version installieren. Die müsste man dann ja selbst kompilieren oder aus einer externen Paketquelle bekommen. In beiden Fällen wäre dann nicht mehr die Distribution für weitere Bugfixes und Sicherheitsupdates zuständig, sondern man müsste sich das selbst drum kümmern.

Ich persönlich habe dieses Problem auch schon gehabt und bin auf ``pdftoppm`` per `subprocess`-Modul ausgewichen. Wobei sich ein Blick in die manpage lohnt, denn neben PPM kann das auch andere Formate direkt selbst schreiben. Man muss das also beispielsweise nicht in ein ``pnmtojpeg`` pipen um eine JPG-Datei zu erstellen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Es läuft endlich :)

Code: Alles auswählen

from pdf2image import convert_from_path
import os


class Presentation:
    """Class that divides a PDF into individual images and converts them to jpg"""

    def __init__(self):
        """Constructor of the class"""
        print('Image erstellt')
        pass

    def convert(self, path, filename, folder_path, folder_name):
        """a method that creates a new project folder split the pdf to pictures and save them in the new folder"""
        folder = os.path.join(folder_path, folder_name)
        os.makedirs(folder)
        pages = convert_from_path(os.path.join(path, filename), 300)
        os.chdir(folder)
        page_number = 1
        for page in pages:
            page.save("{}.jpg".format(page_number), 'JPEG')
            page_number += 1
Danke erstmal :)
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du ignorierst mit konsequenz die Hinweise, die dir hier gegeben werden. Dein os.chdir ist problematisch, und den Zähler kannst du besser mit enumerate bekommen.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und diese Klasse ist immer noch unsinnig und überflüssig.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na die scheint in ein Framework oä zu gehören. Aber gerade dann ist das manipulieren des current directory erst recht riskant. Wenn andere das auch tun....
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Ok das mit dem enumerate verstehe ich noch allerdings hatte ich damit Probleme beim sortieren der Bilder und bei chdir weiß ich nicht wie ich sonst in den neu angelegten Ordner schreiben soll !? Die Klasse wird so benötigt, da sie im model des Projekts liegt und da liegt noch ne GUI drüber etc.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Felix92 hat geschrieben: Sonntag 17. März 2019, 22:59bei chdir weiß ich nicht wie ich sonst in den neu angelegten Ordner schreiben soll !?
Indem du den kompleten Pfad der zur Datei und nicht nur den Dateinamen angibst.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Edit: Dein Programm kann überall dort hinschreiben, zu dem es auch die entsprechenden Berechtigungen hat.
Das aktuelle Verzeichnis zu wechseln ist überhaupt nicht notwendig. Das muss man nur machen, wenn man irgendwelche schlechten Bibliotheken nutzt, die einem keine andere Wahl lassen.

Code: Alles auswählen

from pdf2image import convert_from_path
from pathlib import Path


def convert(path, filename, folder_path, folder_name):
    """a function that creates a new project folder split the pdf to pictures and save them in the new folder"""
    folder = Path(folder_path, folder_name)
    folder.mkdir(exist_ok=True) 
    input_file = Path(path, filename)
    pages = convert_from_path(str(input_file), 300)
    for page_number, page in enumerate(pages, start=1):
        target = folder / f"{page_number:03d}.jpg"
        page.save(str(target),  'JPEG')
Ich bin ein pathlib-faschist.
Code ist nicht getestet. Wenn man noch alte Bibliotheken verwendet, müssen die Path Objekte zuvor in einen String umgewandelt werden.
Das aktuelle Verzeichnis zur Laufzeit des Programms zu wechseln, ist eine ganz schlechte Idee. Eine Klasse mit zwei Methoden ist keine Klasse.
Das ignorieren von Vorschlägen führt dazu, dass du vieles per Hand machst (enumerate z.B.).

Überlege dir andere Namen für die Variablen. path, filename, folder_path, folder_name kann alles mögliche sein.
Nutze nicht die ungarische Notation.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten