Lo-Fi Python

Nov 20, 2018

Packaging Python as a Windows App via Pyinstaller

My research found that for creating a single-file Windows executable from a .py file, the front-running Python library is Pyinstaller. It worked on my Windows 7 PC. My program used a Gooey GUI, but many of the popular Python GUI libraries work as well.

Installation:

To install, enter this into command your command prompt or terminal:
python -m pip install pyinstaller
At the time of this article, this installed Pyinstaller version 3.3.1 using Python version 3.6.5. Go here for a refresher on setting up pip if you need it.

Using the build.spec file and starting Pyinstaller:

Most examples I found used a build.spec file. Think of this as the blueprint by which your app will be constructed. It provides the compiling settings, images and any other data necessary for assembling your app. The format for passing the .spec file to Pyinstaller in pseudo-code:

pyinstaller (run mode options) (.spec file)
Basic start compiler command to build.spec:
pyinstaller build.spec

Establishing a debugging loop with Pyinstaller

Debug mode can be set from the command line:

pyinstaller -debug build.spec

OR by passing debug=True to the EXE() function of the build.spec. I used the second option. See my full build.spec file at the bottom of this post. Pyinstaller displayed a lot of error messages while compiling my app, but it still compiled into a working .exe.

To see your app's error message, run the resulting your_app.exe from the command line. You can find it in the 'dist' folder that pyinstaller creates when you pass it the build.spec file. Set the dist folder as your working directory, type your_app.exe and hit enter. Once you are reading and fixing error messages, you're well on the way to creating your own desktop app.

Flushing sys.stdout/Python printing for Windows:

Python's design requires some code to play nice with Windows when it prints a statement. Simply add this to your .py file. I used write mode 'w'. What worked for me: don't pass 0 to fdopen(). This was contrary to Gooey's instructions.

1
2
3
4
import os
import sys
nonbuffered_stdout = os.fdopen(sys.stdout.fileno(), 'w')
sys.stdout = nonbuffered_stdout

Fetching the local user's system information:

In order to run on any user's system, we need to grab their local file paths. I accomplished this by referencing the sys._MEIPASS via the below code I found from a Stack Overflow post.

1
2
3
4
5
6
7
def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller"""
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

temp_folder_path = getattr(sys, '_MEIPASS', os.getcwd())
relative_path = resource_path(temp_folder_path)

Adding library-specific patches:

  1. Below is the fix I found for the Pandas library, which I added to my build.spec:
1
2
hiddenimports=['pandas._libs.tslibs.timedeltas','pandas._libs.tslibs.nattype',
'pandas._libs.tslibs.np_datetime','pandas._libs.skiplist']

2. The Gooey library needs some special code added to the build.spec for its images and languages data. More details are found in this blog post, written by the author of the Gooey library.

Will Ferrell Old School

Last, but not least: don't panic.

Compiling Python to Windows binary code sounds like a dauntingtask, but it wasn't nearly as complex as I feared. The folks behind Pyinstaller have done a great job of making it possible and, dare I say, simple. Stay calm, drink some coffee, dig in and welcome the challenge with a trial and error mentality. I was able to figure it out over the span of one Saturday. Good luck.

Useful Resources:

  1. Pyinstaller Github - If Things Go Wrong
  2. Pyinstaller Documentation:Using Pyinstaller Arguments
  3. Gooey Pyinstaller Instructions
  4. Pandas hiddenimports Discussion

Caveats:

  1. You should compile the program on the operating system it will be run on. There are options for creating a multi-os compatible package, but I did not attempt them.
  2. Windows 7 is proven to work with Pyinstaller, per the documentation. It's also what I am running on. Other Windows systems older than Windows 10 may be less reliable.
  3. I experienced trouble when passing arguments from the command line to pyinstaller and have so far been unable to get the console window to hide. Neither the -w, --windowed, --noconsole arguments seemed to work. I will update if I am able to find a solution.
  4. Now that I am testing my compiled app, I am seeing 10x performance slowdowns when running as the final .exe vs. the original .py file. But at least the program runs correctly and still does so relatively quickly.
  5. I also received the error: "Fatal error: Pyinstaller does not include a pre-compiled bootloader for your platform." I fixed this by upgrading to the latest version of Pyinstaller:
pip3 install --upgrade pyinstaller

My full build.spec file, modified from here :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- mode: python -*-
import gooey
gooey_root = os.path.dirname(gooey.__file__)
gooey_languages = Tree(os.path.join(gooey_root, 'languages'), prefix = 'gooey/languages')
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images')

a = Analysis(['your_program.py'],
             pathex=['C:\\Python36\\Lib\\site-packages\\your_appdir'],
             hiddenimports=['pandas._libs.tslibs.timedeltas', 'pandas._libs.tslibs.np_datetime', 'pandas._libs.tslibs.nattype', 'pandas._libs.skiplist'],
             hookspath=None,
             runtime_hooks=None,
             )
options = [('u', None, 'OPTION')]
a.datas += [('program_icon.ico', 'C:\\Python36\\Lib\\site-packages\\your_appdir\\program_icon.ico',  'DATA'),
            ('config_icon.png', 'C:\\Python36\\Lib\\site-packages\\your_appdir\\config_icon.png','DATA')]

pyz = PYZ(a.pure)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          options,
          gooey_languages,
          gooey_images,
          name='ADD YOUR APP NAME HERE',
          debug=True,
          strip=False,
          upx=True,
          console=True,
          icon=os.path.join('program_icon.ico'))

Jul 30, 2017

Tips For Creating Useful Ideas

11 Ideas from people who have created great products, businesses, or ideas:

  1. Expertise in a field or product is one of the best assets. Nike's founders started out by making their prototype shoe designs themselves with a waffle iron. //Shoe Dog
  2. Scratch your own itch. Create the product that you wish existed in the world. Write the book you want to read. // Austin Kleon //Indie Hackers
  3. Observe a problem or inconvenience that exists in the world and create a better solution. // Product Development Class
  4. Find a niche and create something useful for that segment of people. //Seth Godin
  5. For every attribute, there is an opposite, effective attribute. //Law 14, The 22 Immutable Laws of Marketing
  6. Launch quickly, show to people, get feedback, and iterate your idea. //Rework
  7. Use combinatory play. Take ideas from different disciplines and combine them to bring about new ideas. //Brain Pickings
  8. Invest in improving your product versus marketing. A great product is obvious to a potential customer. //Seth Godin
  9. People remember how you or your product made them feel versus cost, etc.
  10. An idea doesn't have to be revolutionary. Many new businesses or products take an existing product and make a slight modification or add a new twist.
  11. Many of the successful people during the gold rush sold pick-axes to the miners.

Jul 28, 2017

Should You Go To Programming School?

There is no one-size-fits-all answer. Below are some thoughts that may help you decide.

  1. What are your programming goals? Get a coding job? Create an app or website? Become more productive at your current job?
  2. What is your current experience level? Are you starting fresh or do you already know a language or two?
  3. Do you have money saved up? Otherwise, you might need to take out a loan.

A computer science degree is typically most expensive. Coding bootcamps are a lower cost option that pack a wide curriculum into a few weeks or months, but they can still be pricey. The cheapest option is to take a piecemeal approach through various online courses.

School Advantages

  • Wholistic approach. You get the ins and outs of programming from a proven curriculum.
  • Community. You learn with other students and from experienced teachers.
  • Job placement. Often various schools and bootcamps will connect you to a company.
  • Credentials. You gain confidence and the backing of your skills by an established institution.

Potential Downsides

  • Tuition Money. A lot of what you need to know is available for free or cheap on the web.
  • Skill level match. Some bootcamps are oriented for beginners, others are more advanced. If you do a bootcamp, make sure it fits your skill level.

If you want a coding job, school makes sense. The bootcamps look to be effective if you can handle the up-front investment. It's possible to land a job without schooling but much tougher. I am currently considering Full Stack Academy. and Coding Dojo. There are many out there. CodeAcademy is a popular route as well.

If you want to make an app or website, the school or the non-school route may both work. For the non-school route, the following languages are good places to start: (note - not a comprehensive list, these are my picks.)

  • Web App or Website: HTML, CSS, Python, Javascript
  • Web App or Website Framework: Flask, Django, py4web, Ruby on Rails, React
  • iOS app: Swift plus Apple's Xcode environment, Beeware (python library)
  • Android App: Java or Kotlin, Beeware
  • General Coding: Python or Ruby

If you want to be more productive at work, I recommend learning Python. More on Python and where to start here. Automate the Boring Stuff With Python is a great resource for boosting your productivity also.

It's not easy to decide whether or not school is for you. I'm still unsure after a year and a half of programming on the side. No matter what, continue to learn multiple languages and strive for a better grasp of the ones you know. Good luck!

My decision: continue self-study and learning online for free.

As of 8 months after writing this post, I have concluded that learning for free online was the right choice for me. I've achieved many of my programming goals in the last three years, thanks to materials available from Codeacademy, Coursera, YouTube, Stack Overflow, countless helpful resources,, interesting blogs, and documentation. I've talked with others who need the in-person assistance that a bootcamp offers to learn. Do what works for you. Good luck with your decision.

Update: Several years later, I also get paid to use Python and Excel for a living! I studied for free online intermittently over 2 years to achieve it.