Shawn Driscoll's Tech Blog


Stuff That Happened in the Past

Tuesday, February 25, 2014

Some Sound Advice for Old Python and Py2exe Users

I've recently been working on a hobby Python 2.5 app involving audio from .WAV files. The program uses PyQt4 for its GUI, which was laid out using Qt Designer. This meant that, not only was I using QApplication for my program's chassis, but I could use .QRC files to fuel it.

But first, I want to show a "before" image.

Let's say your Python program plays certain .WAV files during its execution. I happened to be using QSound from PyQt to play the audio. This worked out well enough for me. I had the .WAV files in their own "sounds\" folder. The problem though was when I used Py2exe to distribute my app. I was having to manually copy my .WAV files into the dist folder after each version update because Py2exe didn't know to bundle them. On the Py2exe site, I found this way of getting the copying done for me.


from distutils.core import setup
import py2exe



data_files = [
              (r'sounds', [r'sounds\activated.wav',
                           r'sounds\running_silent.wav',
                           r'sounds\exceptional_failure.wav',
                           r'sounds\exceptional_success.wav',
                           r'sounds\marginal_failure.wav',
                           r'sounds\marginal_success.wav',
                           r'sounds\average_failure.wav',
                           r'sounds\average_success.wav',
                           r'sounds\skill_check.wav',])
             ]


This is just a snip from the setup.py script I use that imports and runs Py2exe. First, a "sounds" folder is created in the "dist" folder. Then the .WAV files are copied to it from their "sounds\" folder. No more having to manually copy these files over each time.

So this was working out swimmingly until I thought I'd give glob a try.


from distutils.core import setup
import py2exe

import glob



data_files = [
              (r'sounds', glob.glob(r'sounds\*.wav'))
             ]


The glob module allows "*.*" copying of files. So that was pretty cool. I didn't have to remember filenames to include in my list.

But then yesterday, I had the great idea I was going to put my .WAV files into a Python script and import it. I would list the filenames in a special .QRC file and then convert it to a Python file. That way the audio files could not be found or tampered with after distributing. Well... The QSound module I was using wanted nothing to do that with. So I went to the Qt Google+ Community and asked if this was even do-able. I was told to use the Phonon module to play such audio files.

Done. Here is a video showing an "after" image.

Monday, February 17, 2014

Wednesday, February 5, 2014

Getting Py2exe to Work With Matplotlib for Python 2.5

I just started playing around with Matplotlib in Python 2.5.4. I love it so far. And, of course, I just had to make a Windows EXE file from a project I was working on. Nothing but crashes using Py2exe until I learned about glob.

The problem I was having was with the Matplotlib data files not being included/found when running the EXE. At the CMD prompt, I enter setup.py py2exe as usual.

The setup.py code is below:


# Used successfully in Python 2.5.4 for py2exe and matplotlib
from distutils.core import setup
import py2exe

import glob
 
opts = {'py2exe': {'includes': ['matplotlib.backends',
                                'matplotlib.backends.backend_qt4agg',
                                'matplotlib.figure', 'pylab', 'numpy',
                                'matplotlib.backends.backend_tkagg'],
                   'excludes': ['_gtkagg', '_tkagg', '_agg2', '_cairo', '_cocoaagg',
                                '_fltkagg', '_gtk', '_gtkcairo'],
                   'dll_excludes': ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll']
                  }
        }

data_files = [(r'mpl-data', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\*.*')),
                  (r'mpl-data', [r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']),
                  (r'mpl-data\images', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\images\*.*')),
                  (r'mpl-data\fonts', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\fonts\*.*'))]

# for console program use "console = [{'script': '3d6_line_bar.py'}]"
# for windows program use "windows = [{'script': '3d6_line_bar.pyw'}]"
setup(windows = [{'script': '3d6_line_bar.pyw'}], options=opts, data_files=data_files)