Seite 1 von 2
PDF-Dateien direkt aus Python heraus drucken
Verfasst: Dienstag 21. April 2015, 19:01
von Nobuddy
Hallo zusammen,
Ich suche eine Möglichkeit, PDF-Dateien direkt aus Python heraus zu drucken.
Mein Betriebssystem ist Linux Kubuntu 14.04 LTS.
Was benötige ich dazu, bzw. gibt es dafür schon etwas Fertiges?
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Mittwoch 22. April 2015, 16:49
von EmaNymton
Wenn es nur für dich unter Linux lauffähig sein soll, würde ich mit Hilfe des subprocess module das Dokument per lp bzw. lpr an den Drucker schicken.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 02:49
von diesch
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 15:00
von Nobuddy
Hallo zusammen,
@EmaNymton, ja ist nur für Linux gedacht, ein kleiner Beispiel-Code, wäre nicht schlecht gewesen.
@diesch, das schaue ich mir mal genauer an, das könnte evtl. passen, DANKE
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 16:10
von EmaNymton
Entschuldige bitte, aber das ist ein Zweizeiler. Ich dachte du kannst mit den von mir genannten Begriffen was anfangen. Selbst wenn nicht, wenn du "lp subprocess" in eine Suchmaschine deiner Wahl eingibst, wirst du mit Sicherheit fündig werden. Ansonsten hilft auch ein "man lp" im Terminal weiter und die Dokumentation zum subprocess-Modul findest du in der offiziellen Python-Doku.
@pycups: AFAIK ist das nur zur Verwaltung von Druckern und nicht zum Drucken selbst gedacht.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 16:56
von BlackJack
@EmaNymton: Es gibt auf `cups.Connection`-Exemplaren eine `printFile()`-Methode wo man Druckername, lokalen Dateinamen, und Optionen angeben kann. Sieht also so aus als könnte man auch damit drucken.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 17:08
von EmaNymton
Sieht nicht nur so aus, geht auch, gerade getestet

Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 17:41
von Nobuddy
test.py und cupstree.py funktionieren fehlerfrei, nur wie kann ich damit eine PDF-Datei mit meinem Drucker ausdrucken?
Vielleicht kann mir das Jemand verraten?
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Donnerstag 23. April 2015, 18:35
von /me
Nobuddy hat geschrieben:Vielleicht kann mir das Jemand verraten?
Um BlackJack zu zitieren: "Es gibt auf `cups.Connection`-Exemplaren eine `printFile()`-Methode wo man Druckername, lokalen Dateinamen, und Optionen angeben kann.".
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Freitag 24. April 2015, 15:59
von Nobuddy
Hallo /me,
habe schon BlackJackś Info gelesen ... und stehe doch auf dem Schlauch. :K
Mittels cupstree.py habe ich Druckernamen und URI, meines LAN-Druckers erhalten.
Wenn ich nicht verkehrt liege, ist die test.py zum Drucken da.
Ich habe diese mal entsprechend editiert und sieht momentan so aus:
Code: Alles auswählen
#!/usr/bin/python
import cups
# Simple demonstration of cups module
PRINTER = 'MFC8860DN'
PRINTERNAME = 'MFC8860DN[@localhost]'
URI = 'socket://192.168.178.30:9100'
FILE = '/home/pfad/zu/meiner/pdf_datei/a.pdf'
def callback(prompt):
print ("Password is required for this operation")
password = raw_input(prompt)
return password
def test_cups_module():
cups.setUser("root")
cups.setPasswordCB(callback)
conn = cups.Connection()
printers = list(conn.getPrinters().keys())
pi = [i for i, printer in enumerate(printers)
if printer == PRINTER][0]
if 0:
file(FILE, "w")
conn.getFile(PRINTERNAME, FILE)
conn.putFile(PRINTERNAME, FILE)
print("Getting PPD for %s" % printers[pi])
f = conn.getPPD(printers[pi])
ppd = cups.PPD(f)
ppd.markDefaults()
print (ppd.conflicts())
groups = ppd.optionGroups
for group in groups:
for opt in group.options:
print(list(map(lambda x: x["text"], opt.choices)))
# conn.printFile(PRINTERNAME, FILE, ??optionen??)
test_cups_module ()
Leider habe ich mit den Optionen erhebliche Schwierigkeiten.
Wäre schön, wenn Ihr mir da weiter helfen könntet!
Bin ich mit einem Teil des Codes auf dem richtigen Weg, oder total verkehrt?
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Freitag 24. April 2015, 18:29
von Nobuddy
Nun habe ich es doch noch geschafft, eine PDF-Datei auszudrucken.
Code: Alles auswählen
#!/usr/bin/python
import cups
# Simple demonstration of cups module
PRINTER = 'MFC8860DN'
PRINTERNAME = 'MFC8860DN[@localhost]'
URI = 'socket://192.168.178.30:9100'
FILE = '/home/pfad/zu/meiner/pdf_datei/a.pdf'
def callback(prompt):
print ("Password is required for this operation")
password = raw_input(prompt)
return password
def test_cups_module():
cups.setUser("root")
cups.setPasswordCB(callback)
conn = cups.Connection()
printers = list(conn.getPrinters().keys())
pi = [i for i, printer in enumerate(printers)
if printer == PRINTER][0]
if 0:
file(FILE, "w")
conn.getFile(PRINTERNAME, FILE)
conn.putFile(PRINTERNAME, FILE)
print("Getting PPD for %s" % printers[pi])
f = conn.getPPD(printers[pi])
ppd = cups.PPD(f)
ppd.markDefaults()
print (ppd.conflicts())
groups = ppd.optionGroups
title = FILE.split("/")[-1]
conn.printFile(PRINTER, FILE, title=title, options={'copies': '1'})
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 11:26
von darktrym
Zum Verständnis wie die API funktioniert ok, aber die sonstige Codequalität wirft Fragen auf.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 12:04
von kbr
Natürlich geht es auch kompliziert. Ich mache dies so:
Code: Alles auswählen
def print_invoice_pdf(path):
"""Print a given pdf-file. path must be absolute."""
subprocess.call(['lp', path])
Solange dies nur lokal läuft, ist es für mich gut genug.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 13:17
von diesch
Nobuddy hat geschrieben:Nun habe ich es doch noch geschafft, eine PDF-Datei auszudrucken.
Als Minimalvariante reicht sowas wie
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cups
PRINTER = 'PDF'
FILE = 'test.pdf'
conn = cups.Connection()
conn.printFile(PRINTER, FILE, title='test', options={})
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 13:26
von Nobuddy
Ja diesch, die Minimalvariante reicht da völlig aus.
Wie ist das bei den options, wenn ich ein 5-seitiges Dokument habe, bei dem ich nur Seite 2 bis 3 ausdrucken möchte?
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 13:40
von diesch
kbr hat geschrieben:Natürlich geht es auch kompliziert. Ich mache dies so:
Code: Alles auswählen
def print_invoice_pdf(path):
"""Print a given pdf-file. path must be absolute."""
subprocess.call(['lp', path])
Solange dies nur lokal läuft, ist es für mich gut genug.
Da musst du dafür sorgen, dass der Pfad nicht mit einem
- anfängt, sonst interpretiert lp das als Option.
Die Lösung funktioniert nur, wenn der Benutzer kein Passwort zum Drucken benötigt. Und sie ist schlecht erweiterbar, wenn du mehr willst, als nur ein Datei mit festen Optionen zu drucken, z.B. auch eine Drucker-Auswahl anbieten.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 14:15
von kbr
@diesch: Absolute Pfade fangen in der Regel nicht mit '-' an. Ansonsten hast Du Recht, dieser Einzeiler schiebt nur eine Datei an den Default-Drucker. Oftmals reicht das ja schon.
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 14:20
von diesch
Nobuddy hat geschrieben:
Wie ist das bei den options, wenn ich ein 5-seitiges Dokument habe, bei dem ich nur Seite 2 bis 3 ausdrucken möchte?
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 16:12
von Nobuddy
Hallo diesch,
Danke für Deine Info!
Ich habe einfach mal etwas herum gespielt und die cupstree.py editiert.
Zuerst habe ich eine Klasse erstellt und dann mit ein paar nützlichen Funktionen versehen.
Ich denke, daß sich mit dem Code von cupstree.py noch einiges mehr sich herausholen lässt.
Hier mal mein Änderungs-Code:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# For Python3.x
import cups
class CUPS_Pool(object):
"""
Erstellung von System-Informationen zu CUPS-Drucker.
"""
def __init__(self, host=None, depth=0):
if host:
cups.setServer(host)
else:
host = "localhost"
c = cups.Connection()
printers = c.getPrinters()
classes = c.getClasses()
self.default_printer = c.getDefault()
self.indent = self.do_indent(depth)
self.ident_number = 0
self.conn = cups.Connection()
self.printerpool = list()
self.printersettings = dict()
for name, queue in printers.items():
self.getqueue(name, queue, host, depth, printers, classes)
def do_indent(self, indent):
return " "*indent
def getippqueue(self, dev, queue, depth):
name = dev.rfind('/')
name = dev[name + 1:]
dev = dev[6:]
e = dev.find(':')
if e == -1:
e = dev.find('/')
host = dev[:e]
cups.setServer(host)
try:
c = cups.Connection()
printers = c.getPrinters()
classes = c.getClasses()
except RuntimeError:
# Failed to connect.
return
except cups.IPPError as e:
if e == cups.IPP_OPERATION_NOT_SUPPORTED:
# CUPS-Get-Printers not supported so not a CUPS server.
printers = {}
classes = {}
else:
return
queue = c.getPrinterAttributes(name)
dev = queue['device-uri']
self.getqueue(name, queue, host, depth + 1, printers, classes)
def getqueue(self, name, queue, host, depth, printers, classes):
self.indent = self.do_indent(depth)
if queue['printer-type'] & cups.CUPS_PRINTER_CLASS:
print("%s* Name:\t%s[@%s] (class)" % (self.indent, name, host))
dev = queue['device-uri']
if dev.startswith('ipp:'):
self.getippqueue(dev, queue, depth)
else:
members = classes[name]
depth += 1
self.indent = self.do_indent(depth)
for member in members:
self.getqueue(member, printers[member], host,
depth, printers, classes)
else:
print("%s* Name:\t%s[@%s]" % (self.indent, name, host))
printer_name = name
printer_host = "%s[@%s]" % (name, host)
dev = queue['device-uri']
info = queue['printer-info']
print("%sURI:\t%s" % (self.indent, dev))
printer_uri = dev
print("%sInfo:\t%s" % (self.indent, info))
printer_info = info
if dev.startswith ('ipp:'):
return self.getippqueue(dev, name, depth)
if depth == 0:
print
master = ''
if self.default_printer == printer_name:
master = 'MASTER'
self.master_printer = printer_name
self.printerpool.append([master, printer_name, printer_host,
printer_uri, printer_info])
# Settings
f = self.conn.getPPD(printer_name)
ppd = cups.PPD(f)
ppd.markDefaults()
groups = ppd.optionGroups
option2selection = dict()
for group in groups:
for opt in group.options:
selection = list(map(lambda x: x["text"], opt.choices))
option2selection[opt] = selection
self.printersettings[printer_name] = option2selection
def printer_pool(self):
"""
Ausgabe von status, printer_name, printer_host, printer_uri
und printer_info.
"""
return sorted(self.printerpool, reverse=True)
def printer_settings(self):
"""
Ausgabe von Drucker-Einstellungen und Auswahl-Einstellungen.
"""
return self.printersettings
def print2document(self, print_file):
"""
Ausführung von Druckauftrag.
"""
title = print_file.split("/")[-1]
try:
self.conn.printFile(self.master_printer, print_file,
title=title, options={})
except cups.IPPError as e:
print('Fehler bei Druckauftrag: %s' % e)
return
def main():
## Erledige Druckauftrag mit Standad-Drucker
# CUPS_Pool().print2document('/pfad/zu/test.pdf')
## Ausgabe Aller CUPS-Drucker
#printer_pool = CUPS_Pool().printer_pool()
try:
print(printer_pool)
except NameError:
pass
## Ausgabe der Drucker-Einstellungen und Auswahl-Einstellungen
## aller CUPS-Drucker.
## dict = (printer_name : {printer_setting : setting_selection})
#printer_settings = CUPS_Pool().printer_settings()
try:
print(printer_settings['MFC8860DN'])
except NameError:
pass
if __name__ == '__main__':
main()
Mit der Funktion 'print2document', übergebe ich nur noch das Druckdokument mit Pfad.
Der Standard-Drucker, wird automatisch übergeben.
Bei Zeile 92:
bin ich mir nicht sicher, ob dies gebraucht wird und welche Aufgabe aus 'print' resultiert.
Grüße Nobuddy
Re: PDF-Dateien direkt aus Python heraus drucken
Verfasst: Samstag 25. April 2015, 18:06
von Nobuddy
Was mich noch interessiert:
Gibt es die Möglichkeit über CUPS, die Info zu erhalten ob der betreffende Drucker überhaupt an und bereit ist?
Dazu habe ich bisher noch nichts finden können.
Grüße Nobuddy