My first gui application is working fine. Fine, that is until the user forgets to select the output directory. I have set up an error message that, when clicked, directs the script to the open directory dialog.

This works but I would prefer the user selected the open directory option from the menu. This is the script that checks that directories are set:

def checkdir(self, event): 
    if indirname=="unset":
        dlg = wx.MessageDialog(self, 'Source and Destination folders not set.','Toadstool v3.2', wx.OK)
        dlg.ShowModal()
        self.chooseout(self)
        dlg.Destroy()

indirname is set to "unset" earlier, "chooseout" is a simple open directory function. So if I decided not to direct the user to "chooseout" where could I send them to simply wait? Obviously just removing the "chooseout" line allows the script to continue and raise an exception. In batch (the only other programming I've done) this would be a job for goto! I'm starting to get an ache behind my eyes, please help.

Not sure how you have this implimented but if the user doesn't chose a directory couldn't you just have the program simply clear the the box and send a messsage to the user stating that the directory they chose does not exist? That way if they chose nothing or an invalid directory both cases are handled.

your post needs clarification. Exactly what do you want to accomplish?

Strangely, nothing!

OK. the variable outdirname has not been set, yet my script wants to save a file to that location. The error is detected and up pops a message box with an OK button.
When the button is clicked the script will continue and generate a traceback exception, unless I use an "if" statement (or whatever) to send it somewhere else.
However, I don't want it to do anything, when the button is clicked I want the GUI to fall idle waiting for input again. I want the user to manually set the directory from the option in my menu.
I hope that is a bit clearer...

Edited 4 Years Ago by floatingshed: n/a

Normally, such redirection is done with a return statement or by raising an exception. I suppose that checkdir() is called by some other function which needs an opened directory, one way to do it is to return a boolean from checkdir

def other_function(self):
    ...
    if not self.checkdir():
        return # abort current action
    ...

where checkdir would be

def checkdir(self): 
    if indirname=="unset":
        dlg = wx.MessageDialog(self, 'Source and Destination folders not set.','Toadstool v3.2', wx.OK)
        dlg.ShowModal()
        dlg.Destroy()
        return False
    else
        return True

You can also raise an exception (more typically pythonic)

class MissingDirectory(Exception):
    pass

def checkdir(self, event): 
    if indirname=="unset":
        dlg = wx.MessageDialog(self, 'Source and Destination folders not set.','Toadstool v3.2', wx.OK)
        dlg.ShowModal()
        dlg.Destroy()
        raise MissingDirectory

def other_function(self):
    ...
    try:
        self.checkdir():
    except MissingDirectory:
        return # abort current action
    ...

The advantage of the exception is that you can choose not to catch it in other_function() but instead in a function that calls other_function().

Edited 4 Years Ago by Gribouillis: n/a

Normally, such redirection is done with a return statement or by raising an exception. I suppose that checkdir() is called by some other function which needs an opened directory, one way to do it is to return a boolean from checkdir

Thanks again for your help. However I'm struggling with this. I understand the first two examples, returning a boolean, but I don't know what to do with that returned data...

I tried your third example and it showed promise but I got the error: AttributeError: 'Toad' object has no attribute 'checkdir' I guess that this is something to do with checkdir now being in your "MissingDirectory" class and not in my "Toad" class. At this stage classes are black magic to me!

I hope I'm not stretching your patience...[code=python]


Thanks again for your help.
However I'm struggling with this. I understand the first two examples, returning a boolean, but I don't know what to do with that returned data...

I tried your third example and it showed promise but I got the error:
AttributeError: 'Toad' object has no attribute 'checkdir' I guess that this is something to do with checkdir now being in your "MissingDirectory" class and not in my "Toad" class.
At this stage classes are black magic to me!

I hope I'm not stretching your patience...

Edited 4 Years Ago by floatingshed: n/a

However I'm struggling with this. I understand the first two examples, returning a boolean, but I don't know what to do with that returned data...

Can't you post the whole code ? Checkdir() must not go in the MissingDirectory class. Leave it where it was.

Edited 4 Years Ago by Gribouillis: n/a

Can't you post the whole code ? Checkdir() must not go in the MissingDirectory class. Leave it where it was.

I've been putting this off. I've seen some very unkind comments about newbie code on the internet! But here goes... (At this stage checkdir is only called from button1, line 114). This is my bare script with non of your suggestions included, at the moment.

#!/usr/bin/python2

import os
import sys
import os.path
import Tkinter
import wx
from subprocess import Popen
from tkFileDialog import askopenfilenames
from tkFileDialog import askdirectory
import tkMessageBox
from Tkinter import *
from pathman import path
import wx
from PythonCard import dialog, model



# Set variables

wavext = '.wav'
mp3ext = '.mp3'
m4aext = '.m4a'



field1="""This is version 3.2 for Python 2.7.
Developed over several very late nights by Andy Marriott.
I hope it was all worth it!. """

#Set current directory unless selected by menu
#indirname = "D:\Python playtime\processed audio"
#outdirname = "D:\Python playtime\processed audio"
indirname = "unset"
outdirname = "unset"


class Command(object):
    """Run a command and capture it's output string, error string and exit status"""

    def __init__(self, command):
        self.command = command 

    def run(self, shell=True):
        import subprocess as sp
        process = sp.Popen(self.command, shell = shell, stdout = sp.PIPE, stderr = sp.PIPE)
        self.pid = process.pid
        self.output, self.error = process.communicate()
        self.failed = process.returncode
        return self

    @property
    def returncode(self):
        return self.failed
        
        
        
         
class Toad(model.Background):
    def on_menuFileAbout_select(self, event):
        result = dialog.alertDialog(self, field1, 'About Toadstool')
        

    def choosein(self, event):
        dlg = wx.DirDialog(self, "Choose Source folder...:", r'D:\\', style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
        if dlg.ShowModal() == wx.ID_OK:
            global indirname
            indirname=os.path.normpath(dlg.GetPath())
            dlg.Destroy() 


    def chooseout(self, event):
        dlg = wx.DirDialog(self, "Select the destination folder...", r'D:\\')
        if dlg.ShowModal() == wx.ID_OK:
            global outdirname
            outdirname=dlg.GetPath()
            dlg.Destroy() 
            
            
    def on_menuFileIndir_select(self, event):
        self.choosein(self)                           
                    
                        
    def on_menuFileOutdir_select(self, event):
        self.chooseout(self)
 

 
    def checkdir(self, event): 
        if indirname=="unset":
            dlg = wx.MessageDialog(self, 'Please set the Source and Destination folders.','Toadstool v3.2', wx.OK)
            dlg.ShowModal()
            #self.choosein(self)
            #self.chooseout(self)
            dlg.Destroy() 

        

    def completed(self, event):        
        dlg = wx.MessageDialog(self, 'Processing completed!','Toadstool v3.2', wx.OK)
        dlg.ShowModal()
        dlg.Destroy()            
          
            
    def status(self, event, text):       
            self.SetStatusText(text)  

            
    def statusclear(self, event):       
            self.SetStatusText("") 
            
       
    def on_Button1_mouseClick(self, event):
            self.checkdir(self)
            self.status(self, "Converting MP3 files to WAV... Please wait.")
            self.mp32wav(self)  
            
    def on_Button2_mouseClick(self, event):
            self.status(self, "Converting WAV files to MP3... Please wait.")
            self.wav2mp3(self) 
            
    def on_Button3_mouseClick(self, event):
            self.status(self, "Converting M4A files to WAV... Please wait.")
            self.m4a2wav(self)         
     
    def on_Button4_mouseClick(self, event):
            self.status(self, "Converting WAV files to M4A... Please wait.")
            self.wav2m4a(self) 
             
    def on_Button5_mouseClick(self, event):
            self.status(self, "Joining WAV files... Please wait.")
            self.joinwav(self) 
         

    def on_Button6_mouseClick(self, event):
            self.status(self, "Joining MP3 files... Please wait.")
            self.joinmp3(self)          
 
        
                    
 # Define MP3 to WAV function #  
   
    def mp32wav(self, event):
 
      list = os.listdir(indirname)
      if len(list)==0:self.SetStatusText("No files found in selected folder") 
      count=0
      mp3 = []
      for eachfile in list:
        if eachfile.endswith(mp3ext):
            mp3.append(eachfile)

      for eachfile in mp3:
         
        infile=(indirname)+"\\"+(eachfile)
        finalin='"'+infile+'"'
        name = os.path.splitext(eachfile)                              
        outname=name[0]+wavext 
        output=os.path.normpath((outdirname)+"\\"+(name[0]+wavext))
        finalout='"'+output+'"'
        args="tools\\Lame.exe --decode "+finalin+" "+finalout
        Command(args).run()
        count=count+1
        
        if count==len(mp3): 
            self.statusclear(self)
            self.completed(self)
            
# End of mp3 to wav function #
#
#
#
# Define wav to mp3 function

    def wav2mp3(self, event):
    
    # Get file list from current directory.    
      cwd = os.getcwd()
      list = os.listdir(indirname)
      if len(list)==0:self.SetStatusText("No files found in selected folder") 
      count=0
      wav = []
    
      for eachfile in list:
        if eachfile.endswith(wavext):
            wav.append(eachfile)
      for eachfile in wav:
        name = os.path.splitext(eachfile)                              
        outfile=name[0]+mp3ext
        app='"'+"tools\\Lame.exe"+'"  '  
        input='"'+indirname+"\\"+eachfile+'"'+" "
        output= '"'+outdirname+"\\"+outfile+'"'
        args='"'+app+input+output+'"'            
        Command(args).run()
        count=count+1
        if count==len(wav): 
            self.statusclear(self)
            self.completed(self)
        
# End of wav to mp3 function #
#                              
#
#
# Define join mp3 function #

    def joinmp3(self, event):
         
        app = path("")/"tools"/"eac3to.exe"
        app2='"'+app+'"'
        indir = path(indirname).hard
        mp3 = [f for f in indir.listdir() if f.ext == '.mp3']
        ofile = path(outdirname).hard/"joined mp3s.mp3"
        arglist = [str(app2), '-log=nul', "+".join('"{0}"'.format(f) for f in mp3), '"{0}"'.format(ofile)]

        args = " ".join(arglist)
        args2='"'+args+'"'
        com = Command(args2).run()
        self.statusclear(self)
        self.completed(self)
          
# End of join mp3 function #
#
#
#
# Joinwav function #

    def joinwav(self, event):

        app = path("")/"tools"/"joinwav.exe"
        app2='"'+app+'"'
        indir = path(indirname).hard
        mp3 = [f for f in indir.listdir() if f.ext == '.wav']
        ofile = path(outdirname).hard/"joined wavs.wav"
        arglist = [str(app2), " ".join('"{0}"'.format(f) for f in mp3), '"{0}"'.format(ofile)]

        args = " ".join(arglist)
        args2='"'+args+'"'
        com = Command(args2).run()
        self.statusclear(self)
        self.completed(self)
        
# End of joinwav function #
#
# 
# 
# Define wav to m4a function

    def wav2m4a(self, event):
    
    # Get file list from current directory.    
      cwd = os.getcwd()
      list = os.listdir(indirname)
      if len(list)==0:self.SetStatusText("No files found in selected folder") 
      wav = []
      count=0
      for eachfile in list:
        if eachfile.endswith(wavext):
            wav.append(eachfile)
      for eachfile in wav:
        name = os.path.splitext(eachfile)                              
        outfile=name[0]+m4aext
        app='"'+"tools\\neroAacEnc.exe" + '"'
        quality=" -lc -q 65.0"
        input=' -if "'+indirname+"\\"+eachfile+'"'+""
        output=' -of "'+outdirname+"\\"+outfile+'"'
        args='"'+app+quality+input+output+'"'            
        com = Command(args).run()
        count=count+1
        if count==len(wav):
            print len(wav) 
            self.statusclear(self)
            self.completed(self)
 
# End of wav to m4a function #
#                              
#
#
# M4A to WAV function]#

    def m4a2wav(self, event):
      list = os.listdir(indirname)
      if len(list)==0:self.SetStatusText("No files found in selected folder") 
      count=0
      m4a = []
    
      for eachfile in list:
        if eachfile.endswith(m4aext):
            m4a.append(eachfile)

      for eachfile in m4a:
        infile=(indirname)+"\\"+(eachfile)
        finalin='"'+infile+'"'
        name = os.path.splitext(eachfile)                              
        outname=name[0]+wavext 
        output=os.path.normpath((outdirname)+"\\"+(name[0]+wavext))
        finalout='"'+output+'"'
        args='"'+"tools\\faad.exe"+'" '+finalin+" "+finalout
        args2='"'+args+'"'
        Command(args2).run()
        count=count+1
        if count==len(m4a): 
            self.statusclear(self)
            self.completed(self)

        
        
# End of m4a to wav function # 



     
if __name__ == '__main__':

    app = model.Application(Toad)
    app.MainLoop()

You could write

def checkdir(self): # DONT NEED EVENT since it's not a callback 
        if indirname=="unset":
            dlg = wx.MessageDialog(self, 'Please set the Source and Destination folders.','Toadstool v3.2', wx.OK)
            dlg.ShowModal()
            #self.choosein(self)
            #self.chooseout(self)
            dlg.Destroy()
            return False
        return True

    def on_Button1_mouseClick(self, event):
            # DONT REPEAT THE 'self' argument when you call methods
            # This needs to be corrected in many of your calls
            if not self.checkdir():
                return
            self.status("Converting MP3 files to WAV... Please wait.")
            self.mp32wav()

Thanks, that does exactly what I want.
Thanks for the pointers about the "self" arguments, I just copied them from the code that was generated by PythonCard and snippets from here. I really don't understand it.

It is taking longer for me to "get it" than I would like...

It is taking longer for me to "get it" than I would like...

Well, programming a GUI, and using a GUI-builder is not exactly the easiest way to begin with python. Hang on until your program works!

Edited 4 Years Ago by Gribouillis: n/a

This article has been dead for over six months. Start a new discussion instead.