rtf oder html auf default Drucker drucken

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.
Antworten
ChristophS
User
Beiträge: 37
Registriert: Montag 7. August 2017, 12:52

Ich komme irgendwie nicht weiter.

Eigentlich ist das Problem an sich trivial. Ich habe ein formatiertes File (rtf/html) und will das mit dem default Drucker zu Papier bringen.
Diesen Nachmittag habe ich damit verbracht mittels DuckDuckGo nach einem Ansatz zu suchen.
zB. python printing lp, python printing html (rtf) oder python printing to default printer ergibt sehr viel wissenswertes zur print() Funktion. Unter Windows kann mit win32 drucken, aber unter Linux / OSX scheint es so einfach zu sein, dass es keine dazu Einträge gibt.

Reinen Text zu drucken ist kein Problem:
text = open('TestFile.html', 'r')
textFile = text.read()
printer = os.popen('lpr', 'w')
printer.write(textFile)
printer.close()
Kann mir jemand einen Hinweis geben?
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ChristophS: Der Hinweis ist das „Eigentlich ist das Problem an sich trivial.“ halt nicht stimmt. Wie kommst Du darauf das sei trivial?

Dein Beispiel zum drucken von Text ist auch nicht so toll. `os.popen()` sollte man nicht verwenden, das macht man mit dem `subprocess`-Modul. `text` und `textFile` hast Du offensichtlich die Namen vertauscht und `textFile` müsste eigentlich `text_file` heissen. Dateien die man öffnet, sollte man auch wieder schliessen. Am besten über die ``with``-Anweisung, damit man sich das ``try``/``finally`` spart.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
ChristophS
User
Beiträge: 37
Registriert: Montag 7. August 2017, 12:52

@__blackjack__
Danke für die Hinweise. Meine korrigierte Version:
import subprocess as sb

lpr = sb.Popen("/usr/bin/lpr", stdin=sb.PIPE)
data = open('/Volumes/Projects/TempControl/TestFile.html', 'rb')
print_data = data.read()
data.close()
lpr.stdin.write(print_data)
Das TestFile.html wird als Text gedruckt. TestFile.html.pdf ergibt ein leeres Blatt.

Mittlerweile habe ich pycups installiert
conn = cups.Connection ()
printer_name = 'Brother_HL_2130_series_2'
conn.printFile(printer_name, '/Volumes/Projects/TempControl/TestFile.html', '', {})
Das Ergebnis ist gleich wie mit subprocesses: *.html == text; *.html.pdf ==leere Seite.

Eine Dokumentation zu pycups habe ich nicht gefunden. Weiss jemand wo es das geben könnte? Mir würde schon genügen, wenn ich wenigstens eine Liste mit den Connection() Attributen hätte.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@ChristophS: Es ist möglicherweise einfacher, ein Dienstprogramm über 'run' anzusprechen, das dann wiederum mit CUPS kommuniziert. Je nach Betriebssystem mag das variieren. Das könnte dann so ähnlich aussehen wie hier:

Code: Alles auswählen

import subprocess

fname = 'document.pdf'
subprocess.run(['lp', fname])
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ChristophS: `subprocess` sollte man nicht mit `sb` abkürzen.

Statt die Datei zu lesen und den Inhalt in `stdin` vom externen Prozess zu schreiben, kann man auch einfach die Datei öffnen und als `stdin` an den externen Prozess übergeben.

Die ``with``-Anweisung macht spart eine Zeile, wenn man ``try``/``finally`` verwendet hätte, sogar noch mehr.

Der Code wartet gar nicht auf das Ende des externen Prozesses. Es kann also passieren das der externe Kindprozess beendet wird weil der Elternprozess am Ende ankommt, bevor der Kindprozess komplett durchgelaufen ist.

Statt ein `Popen()`-Exemplar zu erzeugen und da dann `wait()` drauf aufzurufen, kann man auch einfach `subprocess.run()` verwenden. Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import subprocess


def main():
    with open('/Volumes/Projects/TempControl/TestFile.html', 'rb') as file:
        subprocess.run(['/usr/bin/lpr'], stdin=file)


if __name__ == '__main__':
    main()
PDF-Dateien sollte CUPS eigentlich drucken können. HTML nur wenn ein entsprechender Filter installiert/konfiguriert wurde, denn Standard ist das hier:

Code: Alles auswählen

$ cupsfilter --list-filters test.html
texttopdf
Also eine Umwandlung von Text nach PDF, das dann gedruckt werden kann. Wobei man wenn man die Daten direkt in ``lpr`` hinein piped eventuell noch per Option verraten muss was der MIME-Typ der Daten ist, nur für den Fall das CUPS da falsch rät.

Im Netz habe ich auch keine Dokumentation für `pycups` gefunden, aber das Modul selbst enthält Docstrings, man kann da also in einer interaktiven Python-Shell mit `help()` (oder beispielsweise ``?`` in IPython) oder mit ``pydoc`` heran kommen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten