1

I am making a small program in Python (PyGTK) that prints out a calendar (Gregorian) for a year the user inputs.

Here is my code:

#!/usr/bin/env python

import pygtk, gtk, subprocess
pygtk.require("2.0")

class Base:
    def printing(self, widget):
        text = self.textbox.get_text()
        printingit = "cal -y %s | lpr" % (text)
        process = subprocess.Popen(printingit.split(), stdout=subprocess.PIPE)
        output = process.communicate()[0]   

    def __init__(self):
            self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
            self.win.set_position(gtk.WIN_POS_CENTER)
            self.win.set_size_request(350, 200)
        self.win.set_resizable(False)
        self.win.set_title("Calendar")
        self.win.connect('destroy',lambda w: gtk.main_quit())

        self.textbox = gtk.Entry()
        self.textbox.set_size_request(70, 30)

        self.lable = gtk.Label("Year:")

        self.button = gtk.Button("Print")
        self.button.set_size_request(60, 45)
        self.button.connect("clicked", self.printing)

        box = gtk.Fixed()
        box.put(self.lable, 160, 25)
        box.put(self.textbox, 140, 40)
        box.put(self.button, 145, 100)

        self.win.add(box)
        self.win.show_all()

    def main(self):
        gtk.main()

if __name__ == "__main__":
    base = Base()
    base.main()

It's not working when actually printing the command cal -y %s | lpr % (text). I have made it so it replaces the textbox's text with the final command it should get and it changes to what I want it to be cal -y 2015 | lpr. I tried just putting that into terminal and it worked as usual, it's confusing me a lot!

I ran the program in terminal and this is the message I recieve when it tries to print:

Usage: cal [general options] [-hjy] [[month] year]
   cal [general options] [-hj] [-m month] [year]
   ncal [general options] [-bhJjpwySM] [-s country_code] [[month] year]
   ncal [general options] [-bhJeoSM] [year]
General options: [-NC3] [-A months] [-B months]
For debug the highlighting: [-H yyyy-mm-dd] [-d yyyy-mm]

If anyone understands why this is happening I would be extremely grateful! Thank you in advance =D

  • Harry
  • 1
    What flavour of "not working"? Errors (provide full traceback)? Unexpected outputs (provide inputs and expected and actual outputs)? – jonrsharpe Apr 27 '14 at 20:57
  • What I meant by not working was it wasn't printing (like onto paper) from my default printer. All the errors I received were what I posted and the only output was a frozen program and the error in my terminal. In the text field I input 2015 and got the output I posted. – Skimmed Milk Apr 27 '14 at 21:01
  • Why are you wrapping your procedural code in a useless class? Is this some sort of infection by Java? – Erik Kaplun Apr 27 '14 at 22:25
  • @ErikAllik I am using a class to call the main function without an error. This is simply because I don't know another way of doing this =D – Skimmed Milk Apr 28 '14 at 15:50

1 Answers1

1

If you want to use shell syntax (pipe) in your command, you need to pass the command as as string to the Popen constructor, not as list. And you must use shell=True:

output = subprocess.check_output(printingit, shell=True)

Without that, the executed command would be the same as:

cal '-y' 'text' '|' 'lpr'

But as you're getting part of the input from a text field, you shouldn't directly pass it tho a shell.

Alternatively, you can create the pipe yourself:

lpr = subprocess.Popen('lpr', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
process = subprocess.Popen(['cal', '-y', text], stdout=lpr.stdin)
output = lpr.communicate()
process.wait()

By the way, instead of using subprocess to invoke cal you could use the calendar module. cal -y 2012 does the same as calendar.calendar(2014), so you could replace your code with:

cal = calendar.calendar(int(text))
process = subprocess.Popen(['lpr'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = process.communicate(cal)   # cal.encode(locale.getpreferredencoding(False)) for python3
mata
  • 67,110
  • 10
  • 163
  • 162