Can I send print jobs directly from a python program to the IP address of a CUPS print server?
Asked Answered
S

1

6

I have two linux computers with fixed IP addresses:

  1. A print server, whereby the connected printer is shared via CUPS.
    (The server has the IP address "192.168.1.2" and the printer is called "test_printer".)
  2. A computer, on which a python application is running, that should be able to use this print server.

Unfortunately, the printer propagation via CUPS seems not to work reliably (possibly due to the structure of the network).

Can I send print jobs directly from a python program to the CUPS print server?
If so, can you please provide a small example?

In theory, I would just send correctly formatted data to the IP address + port, but I didn't get it to work ...


Here are the approaches I have found so far and my problems with them:

  • command 'lpr'

    import subprocess
    
    lpr = subprocess.Popen("usr/bin/lpr", stdin=subprocess.PIPE)        # on some distros the command is 'lp'
    lpr.stdin.write("hello world\n")
    lpr.stdin.close()
    

    Relies on the printer propagation via CUPS.


  • python module pycups

    import cups
    
    with open("/home/user/Documents/some.txt", "w") as f:
        f.write("hello world\n")
    
    conn = cups.Connection()
    conn.printFile("test_printer", "/home/user/Documents/some.txt", "some_title", {})
    

    Before I can use a printer, I'll have to add it first, which in turn relies on the propagation via CUPS.
    Also I didn't get conn.addPrinter() to work.


  • python module python-escpos / python-printer-escpos

    import escpos.printer
    
    p = escpos.printer.Network("192.168.1.2", port=631)        # port 9100 seems not to work.
    p.text("hello world\n")
    p.close()
    

    Probably the most promising approach ... unfortunately it doesn't print anything and throws an exception on closing.

    # The traceback was produced in the interactive shell.
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/home/user/.local/lib/python3.6/site-package/escpos/printer.py", line 214, in close
            self.device.shutdown(socket.SHUT_RDWR)
    OSError: [Errno 107] Transport endpoint is not connected
    



I use python 3.6.7.
The print server uses CUPS 2.2.1.

Sinciput answered 5/12, 2018 at 18:42 Comment(4)
Can you be a bit more explicit about what's wrong with the solutions you've tried? Does anything actually print? What does "reliable" mean in this context?Colincolinson
I have revised the question and changed its focus. Hopefully the problem is now better presented.Sinciput
@KurtPfeifle: Please turn your comments into an answer so I can up-vote it. :)Urticaria
@EthanFurman: Done.Youngman
Y
2

Not being a Python programmer, I cannot provide any sample code.

But I can give you some other hints:

  1. Your assumption, that "in theory, [....] just send correctly formatted data to the IP address + port" is wrong.

    If you send something, you have to "talk IPP" to the CUPS server (yes, via the IP address + port 631). But just sending a file is so much less than talking IPP.

    Else, you could use 'netcat IPaddress port-no < filename' to print to any CUPS queue (which would be a huge security issue).

    So you HAVE to use some IPP-capable library, if you want to integrate your program with IPP/CUPS

  2. One alternative could be that you let your program do the "IPP talk to CUPS" by a CLI tool which is capable of doing so.

    Have a look at the ippsample code of the Printer Working Group (PWG) which designed the IPP. That is in "beta" still but already fully usable. All its binaries are command line (CLI) utilities:

    • It provides the ippfind helper tool. If you run it without any parameters, it will print a list of available IPP Services (print servers and/or printer devices) by printing their respective IPP URIs.

    • It provides an ippserver command line, which can start up a fully-fledged, you guessed it, IPP Server exposing any feature you want.

    • Then there is ipptool included as an IPP Client. You could run 'ipptool -f myprintfile -t -v ipp://cupsserver/printers/test_printer print-job.test' to send "myprintfile" to the queue "test_printer" on "cupsserver" (given with example IPP URI ipp://cupsserver/printers/test_printer) and watch it talk IPP to CUPS while it does so.

  See also my ASCIIcast "[TUTORIAL] IPP Sample Software (made with an AppImage)" here. {https://asciinema.org/a/155588 }. Hint: if it plays too fast to follow and understand the screens in time, use the 'pause' button, read at your own speed, then resume playing.

Youngman answered 13/2, 2019 at 21:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.