I’ve been working on creating GUI front ends for command line programs and all the help I’ve gotten here has been amazing. I can never thank you guys enough.
Here’s a test program I’ve been working on that displays the contents of a .CAB file in Windows:
#!python2.7
import sys
import os
from tkFileDialog import *
from subprocess import *
from Tkinter import *
def getfilename():
blankline = 0 # counter to help remove blank lines
filename = askopenfilename(filetypes=[("All files","*"), ("Cab files","*.cab")]) # get the filename
if filename == "": # if the user hits the Cancel button, don't change anything in the list box
return
listbox.delete(0, END) # clear the list box
numberinlist = 0 # count the number of lines in the list box to delete the extra blank line at the end of the list
if os.name == 'nt': # send the command without opening a command window
start_info = subprocess.STARTUPINFO()
start_info.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
commandline = Popen(['expand', '-D', filename], shell=False, stdout=PIPE, stdin=PIPE, stderr=STDOUT, startupinfo=start_info)
# commend the above 4 lines and uncomment the below line and the program works but opens a command window
#commandline = Popen(['expand', '-D', filename], shell=False, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
while True: # read expand.exe's output and strip undeeded characters at the end of each line
listboxline = commandline.stdout.readline().rstrip()
listbox.insert(END, listboxline)
numberinlist += 1
if len(listboxline) ==0: # check for blank lines
blankline += 1
if blankline == 3: # expand.exe sends an extra three blank lines, see if it's the third blank line
listbox.delete(numberinlist - 1) # if it is the third blank line remove the extra line at the end
break # quit the while loop, expand.exe is finished after the third blank line
# set up the window
mywindow = Tk()
mywindow.geometry('400x400')
# add a frame to position the list box in
frame1 = Frame(mywindow)
frame1.pack(fill=BOTH, expand=1)
# name the scroll bars
vertscrollbar = Scrollbar(frame1, orient=VERTICAL)
horzscrollbar = Scrollbar(frame1, orient=HORIZONTAL)
# name the list box and attach the scroll bars
listbox = Listbox(frame1, selectmode=EXTENDED, yscrollcommand=vertscrollbar.set, xscrollcommand=horzscrollbar.set)
vertscrollbar.config(command=listbox.yview)
horzscrollbar.config(command=listbox.xview)
# create the scroll bars and list box
vertscrollbar.pack(side=RIGHT, fill=Y)
horzscrollbar.pack(side=BOTTOM, fill=X)
listbox.pack(side=LEFT, fill=BOTH, expand=1)
# add another frame to position the button in
frame2 = Frame(mywindow)
frame2.pack(fill=X)
# create the button and tell it to go to the getfilename function when clicked
filebutton = Button(frame2, text="Open cab file", command=getfilename)
filebutton.pack()
# start the GUI
mywindow.mainloop()
I’ve added lots of comments so if someone is searching for the answer to a different problem they might find the answer in this program example. The idea is to display the results of ‘expand.exe -D’ line by line into a list box without having the Windows, command line, shell window pop-up, instead keeping it in the background. As you can see from the first line (shebang) I’m using Python 2.7. The problem I’m having is I’m getting the error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "D:\Python\2.7\listcab.pyw", line 17, in getfilename
start_info = subprocess.STARTUPINFO()
NameError: global name 'subprocess' is not defined
I’ve been searching stackoverflow and Google for this error but I’ve been unable to find anything. I’m sure it’s a simple problem with my import list but I have no idea what it is. I still don’t fully understand Python’s different import commands, which to use, when to use them and what the difference between them is.
Since you used a star import…
you shouldn’t be prefixing things you imported from it:
should actually be just…
If you want to use prefixes, you’d want to just do…
which instead of importing all of the names from
subprocessinto the global namespace, just importssubprocessitself, letting you then use its names with the prefix.Then you’d use things like
subprocess.Popen(),subprocess.STARTUPINFO(), et cetera.This is generally considered the preferred way to do imports; it avoids name collisions if two different modules have similarly named functions, and makes it clearer where things came from.