Share the Knowledge
RSS icon Home icon
  • Simple Python program to help improve your Spanish vocabulary

    Posted on February 4th, 2012 webmaster No comments         Print Print

    I’ve been taking 4 hours of Spanish lessons in Antigua, Guatemala for the last 4 days now.  I’ve learned a lot in this last 4 days but I still have a ton to learn.  My Spanish vocabulary needs a lot of work, so I wrote this simple Python program to help me.

    What the program does is load a list of words from a CSV file (I export my CSV files from Google Docs), shuffles them, iterates through the them, gives you the English word, and asks you to enter the Spanish word.  If you answer correctly, it will go to the next word.  If you answer incorrectly, you have the option to try again or tell the program to give you the answer.

    The program keeps track of the words you were not able to answer and shows them to you once it finishes going through all the words for you to review.

    import sys
    import csv
    import random
    
    def get_wordlist(filepath):
        wordlist = {}
        try:
            with open(filepath, 'rb') as f:
                reader = csv.reader(f, delimiter=',')
                for row in reader:
                    wordlist['%s' % row[0].strip().lower()] = \
                    '%s' % row[1].strip().lower()
        except IOError:
            print "\nCould not open %s!\nExiting..." % filepath
            sys.exit(1)
        return wordlist
    
    def get_answer(english_word, wordlist):
        print "\n[%s word(s) remaining]" % len(wordlist.items())
        print "\nEnglish: %s" % english_word
        return raw_input('Spanish: ').strip().lower()
    
    def get_option():
        print "\n[1] Try again.\n[2] Show answer."
        return raw_input("\nEnter option number: ").strip().lower()
    
    if __name__ == '__main__':
        wordfile = raw_input('\nPlease enter the path of the word list file: ')
        wordlist = get_wordlist(wordfile.strip().lower())
    
        # Shuffle the dictionary keys so the objects will be displayed
        # in random order to the user.
        keys = wordlist.keys()
        random.shuffle(keys)
    
        # Keep track of incorrect answers here.
        missed_words = {}
    
        # Pretty ugly for loop. Should refactor later (ok, I confess,
        # I probably won't get to it).
        for key in keys:
            def handle_correct_answer():
                print "\nCorrecto!"
                wordlist.pop(key)
    
            def handle_incorrect_answer():
                print "\nIncorrecto!"
    
            if get_answer(wordlist[key], wordlist) == key:
                handle_correct_answer()
            else:
                handle_incorrect_answer()
                while True:
                    option = get_option()
                    if option == '1':
                        if get_answer(wordlist[key], wordlist) == key:
                            handle_correct_answer()
                            break
                        handle_incorrect_answer()
                    elif option == '2':
                        print "\nThe correct answer is '%s'" % key.upper()
                        missed_words[key] = wordlist[key]
                        wordlist.pop(key)
                        break
                    else:
                        print "\nInvalid option, amigo! Put down the cerveza."
    
        # Display words that were missed and the answers.
        if missed_words:
            print "\nBelow are the word(s) that you missed.\n"
            for key, value in missed_words.items():
                print "%s - %s" % (key.upper(), value)
    

    Read the rest of this entry »

  • Python script for auto-renaming your image files

    Posted on January 19th, 2012 webmaster No comments         Print Print

    I like to rename my pictures a certain way as soon as I import them to my computer.  I usually follow this format: description_datetaken_3digitnumbering.jpg

    I was using Metamorphose to do this for a while.  But one time I wanted to rename my pictures while I was in New Zealand and realized I didn’t have the application installed on my netbook.  I didn’t want to pay the $5 for the Internet access so I decided to just hack together a simple Python script to do it.  I haven’t gone back to Metamorphose ever since.  I found my script easier to use as I had it customized for my needs.

    I’ve tweaked it quite a bit to make it even more user friendly.  Here’s the script if you’re interested. Note that I’m not sure whether the EXIF tag attributes are the same for your camera, so you might need to modify it a little to work for you.

    import os
    import sys
    import shutil
    import datetime
    from PIL import Image
    from PIL.ExifTags import TAGS
    
    # Check first if the given path exists before continuing to the next step.
    while True:
        folderpath = raw_input('Folder path: ')
        print "\nChecking if folder path exists...\n"
        if os.path.exists(folderpath):
            print "Ok!\n"
            break;
        else:
            print "%s does not exist. Please enter a valid path.\n" % folderpath
    
    filename_pattern = raw_input('Filename pattern: ')
    
    def get_exif_data(filename):
        """Get embedded EXIF data from image file.
    
        Source: http://www.endlesslycurious.com/2011/05/11/extracting-image-
                exif-data-with-python/
        """
        ret = {}
        try:
            img = Image.open(filename)
            if hasattr( img, '_getexif' ):
                exifinfo = img._getexif()
                if exifinfo != None:
                    for tag, value in exifinfo.items():
                        decoded = TAGS.get(tag, tag)
                        ret[decoded] = value
        except IOError:
            print 'IOERROR ' + filename
        return ret
    
    def get_date_taken(filename):
        datestring = get_exif_data(current_file)['DateTimeOriginal']
        return datetime.datetime.strptime(datestring, '%Y:%m:%d %H:%M:%S')
    
    def get_filenames():
        os.chdir(folderpath)
        return os.listdir(os.getcwd())
    
    def get_numbering_format(digits, num):
        if digits == 1:
            numberfmt = '00%s' % num
        elif digits == 2:
            numberfmt = '0%s' % num
        else:
            numberfmt = '%s' % num
        return numberfmt
    
    def date_to_string(dateobj, format):
        return datetime.datetime.strftime(dateobj, format)
    
    def multi_replace(text, dictobj):
        """Replace characters in the text based on the given dictionary."""
        for k, v in dictobj.iteritems():
            text = text.replace(k, v)
        return text
    
    if __name__ == '__main__':
        filenames = get_filenames()
        for i in xrange(len(filenames)):
            num = i + 1
            digits = len(str(num))
            current_file = filenames[i]
    
            # Only rename files, ignore directories.
            if not os.path.isdir(current_file):
                # Key, value pairs of what to replace.
                dictobj = {
                    '<num>': get_numbering_format(digits, num),
                    '<datetaken>': date_to_string(get_date_taken(current_file),
                                                  '%Y%m%d')
                }
                new_filename = multi_replace(filename_pattern, dictobj)
                shutil.move(current_file, new_filename)
    

    Sample Usage

    Notes

    • PIL (Python Imaging Library) is required to retrieve the EXIF data.
    • I decided not to traverse subdirectories as that could be pretty dangerous if the wrong path is accidentally entered.
    • It’s set to pad the numbering to 3 digits.
    • It will rename any file that is not a directory (maybe add a check later for file type).
  • How to zip an entire directory with Python

    Posted on January 22nd, 2011 webmaster 4 comments         Print Print

    I’m finally done with the Python project I’m working on and now just working on the build script.  I want my build script to zip the entire build directory at the end so at first I got lazy and I figured I’d just call an external zip application (7-Zip) and let it do all the work.  This would of course require the person doing the build to have 7-Zip installed, so I decided it’s probably better in the long run to write it completely in Python.

    Python has a built-in module called zipfile that can do this.  Zipping just one file is pretty straightforward, but zipping an entire directory is actually trickier than I thought.  I figured at first I could probably just use os.listdir() and have a for loop to add each item in the os.listdir() output to the zip file.  But it turned out this doesn’t return the full paths and doesn’t go through the subfolders.  I then tried glob.glob(), which returns the full paths but like os.listdir() it doesn’t do subfolders.

    After a little bit of searching, I found out that there’s a function called os.walk() that traverses the entire folder structure and returns the paths of the root, subfolders, and files which is exactly what I needed.  I had to play with it a bit to be able to do what I needed.  For example, when I zip the folder, I want the first item in the zip archive to be the folder I specified to zip.  In order to do this, I had to retrieve the paths relative to that folder.  I also wanted empty subfolders to be included in the archive as I have empty folders in my project such as the logs and reports folders.

    Below is what I was able to come up with.  Again, I’m a Python newbie so probably not the most elegant implementation, so I’m open to any suggestions :D .

    import zipfile
    import sys
    import os
    
    def zip_folder(folder_path, output_path):
        """Zip the contents of an entire folder (with that folder included
        in the archive). Empty subfolders will be included in the archive
        as well.
        """
        parent_folder = os.path.dirname(folder_path)
        # Retrieve the paths of the folder contents.
        contents = os.walk(folder_path)
        try:
            zip_file = zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED)
            for root, folders, files in contents:
                # Include all subfolders, including empty ones.
                for folder_name in folders:
                    absolute_path = os.path.join(root, folder_name)
                    relative_path = absolute_path.replace(parent_folder + '\\',
                                                          '')
                    print "Adding '%s' to archive." % absolute_path
                    zip_file.write(absolute_path, relative_path)
                for file_name in files:
                    absolute_path = os.path.join(root, file_name)
                    relative_path = absolute_path.replace(parent_folder + '\\',
                                                          '')
                    print "Adding '%s' to archive." % absolute_path
                    zip_file.write(absolute_path, relative_path)
            print "'%s' created successfully." % output_path
        except IOError, message:
            print message
            sys.exit(1)
        except OSError, message:
            print message
            sys.exit(1)
        except zipfile.BadZipfile, message:
            print message
            sys.exit(1)
        finally:
            zip_file.close()
    
    ## TEST ##
    if __name__ == '__main__':
        zip_folder(r'D:\[STORAGE]\Software\TrueCrypt',
                   r'D:\[STORAGE]\Software\TrueCrypt.zip')
    

    Read the rest of this entry »