Skip to main content

Ralsina.Me — Roberto Alsina's website

Anvil of Stars (Forge of God, #2)

Cover for Anvil of Stars (Forge of God, #2)

Review:

Yet an­oth­er looooong slooooow build to... well, to not much. Not re­al­ly a fun book, not re­al­ly a deep book, not re­al­ly much at al­l. Feels much longer than it is.

Shipping your PyQt app for windows

I have writ­ten about this in the past, with the gen­er­al con­clu­sion be­ing "it's a pain in the as­s".

So, now, here is how it's done.

  1. Start with a work­ing PyQt ap­­pli­­ca­­tion. In this ex­am­­ple, I will use de­vi­­cen­­zo.py most­­ly be­­cause:

    1. It is a work­ing PyQt ap­­­pli­­­ca­­­tion.

    2. It us­es a big chunk of PyQt

    3. It's easy to test

  2. Now you need a set­up.py. Here's one that work­s, with ex­ten­sive com­m­ments.

# We will be using py2exe to build the binaries.
# You may use other tools, but I know this one.

from distutils.core import setup
import py2exe

# Now you need to pass arguments to setup
# windows is a list of scripts that have their own UI and
# thus don't need to run in a console.

setup(windows=['devicenzo.py'],
      options={

# And now, configure py2exe by passing more options;

          'py2exe': {

# This is magic: if you don't add these, your .exe may
# or may not work on older/newer versions of windows.

              "dll_excludes": [
                  "MSVCP90.dll",
                  "MSWSOCK.dll",
                  "mswsock.dll",
                  "powrprof.dll",
                  ],

# Py2exe will not figure out that you need these on its own.
# You may need one, the other, or both.

              'includes': [
                  'sip',
                  'PyQt4.QtNetwork',
                  ],

# Optional: make one big exe with everything in it, or
# a folder with many things in it. Your choice
#             'bundle_files': 1,
          }
      },

# Qt's dynamically loaded plugins and py2exe really don't
# get along.

data_files = [
            ('phonon_backend', [
                'C:\Python27\Lib\site-packages\PyQt4\plugins\phonon_backend\phonon_ds94.dll'
                ]),
            ('imageplugins', [
            'c:\Python27\lib\site-packages\PyQt4\plugins\imageformats\qgif4.dll',
            'c:\Python27\lib\site-packages\PyQt4\plugins\imageformats\qjpeg4.dll',
            'c:\Python27\lib\site-packages\PyQt4\plugins\imageformats\qsvg4.dll',
            ]),
],

# If you choose the bundle above, you may want to use this, too.
#     zipfile=None,
)
  1. Run python set­up.py py2exe and get a dist fold­er full of bi­na­ry good­ness.

And that's it. Ex­cept of course, that's not it.

What this will do is cre­ate a bi­na­ry set, ei­ther a fold­er full of things, or a sin­gle EXE file. And that's not enough. You have to con­sid­er at least the fol­low­ing:

  1. Put ev­ery­thing in re­­source files: im­ages, qss files, icon­s, etc. Ev­ery file your app need­s? Put it in a re­­source file and load it from there. That way you don't have to care about them if you go the "one ex­e" road.

  2. Com­pile .ui files to .py (same rea­­son)

  3. Fig­ure out if you use Qt's plu­g­in­s, and make them work. This in­­­cludes: us­ing Phonon, us­ing Qt­SQL, and us­ing any im­age for­­mats oth­­er than PNG.

Af­ter you have that, are you done? NO!

Your win­dows us­er will want an in­stall­er. I am not go­ing to go in­to de­tail­s, but I had a good time us­ing Bi­tRock­'s In­stall­Builder for Qt. It's a nice tool, and it work­s. That's a lot in this field.

But is that al­l? NO!

You have to take care of the Vis­ual Stu­dio Run­time. My sug­ges­tion? Get a copy of the 1.1MB vcre­dis­t_x86.exe (not the larg­er one, the 1.1MB one), and ei­ther tell peo­ple to in­stall it man­u­al­ly, or add it to your in­stall­er. You are legal­ly al­lowed (AFAIK) to re­dis­tribute that thing as a whole. But not what's in it (un­less you have a VS li­cense).

And we are done? NO!

Once you run your app "in­stalled", if it ev­er prints any­thing to stder­r, you will get ei­ther a di­a­log telling you it did, or worse (if you are in ay­thing new­er than XP), a di­a­log telling you it can't write to a log file, and the app will nev­er work again.

This is be­cause py2exe catch­es stderr and tries to save it on a log­file. Which it tries to cre­ate in the same fold­er as the bi­na­ry. Which is usu­al­ly not al­lowed be­cause of per­mis­sion­s.

So­lu­tion? Your app should nev­er write to stder­r. Write an ex­cepthook and catch that. And then re­move stderr or re­place it with a log file, or some­thing. Just don't let py2exe do it, be­cause the way py2exe does it is bro­ken.

And is that it?

Well, ba­si­cal­ly yes. Of course you should get 4 or 5 dif­fer­ent ver­sions of win­dows to test it on, but you are pret­ty much free to ship your app as you wish. Oh, mind you, don't up­load it to down­load­s.­com be­cause they will wrap your in­stall­er in a larg­er one that in­stalls bloat­ware and crap.

So, there you go.

As I was saying yesterday...

I have not post­ed in this blog in a long time.One ofthe rea­sons is that a whole lot of things have hap­pened in my life, and I have not blogged about them.

It has got­ten so that if I were to "catchup" here, I would need to post a 35-­page post with 300 pic­tures, 100 code snip­pet­s, 50 rants and maybe 3 youtube videos.

So... screw that and let's pre­tend that was all a dream and that you (if there are still any "y­ou" out there) have not been ne­glect­ed, and all is good.

So, what am I post­ing about? Oh, just a short rant.

I am sad­dened and pissed off by peo­ple who proud­ly say "I don't know any­thing about X", where X is math, knit­ting, as­tro­physic­s, foot­bal­l, medicine, pet care, hair­dress­ing, cof­fee brew­ing, pol­i­tic­s, or dol­phin-rear­ing (this does­n't ap­ply to wine. It's per­fect­ly ok not to care about wine, be­cause most peo­ple who do care about wine are fak­ing it).

There are tons of things I know noth­ing about. And you know what? Each one is a per­son­al fail­ure. Ev­ery time I see my mom knit­ting, and I sim­ply can­not grasp how the hell it work­s, it piss­es me of­f.

While it looks mind-crush­ing­ly bor­ing, she's ba­si­cal­ly tak­ing a string, make some knots us­ing stick­s, and pro­duc­ing a freak­ing sweater. How cool is that? I say pret­ty damn cool.

When­ev­er I see some­thing that looks bor­ing, or un­in­ter­est­ing, I al­ways think, there is, some­where, a per­son who has spent years of his life be­ing the best at that. There is, some­where, a per­son which is the world's au­thor­i­ty on how to tie a string to make a sweater.

There is some­one who is the non-­plus-ul­tra of lay­ing out coloured tiles so it looks good in the shape of a dol­phin.

There is some­one who is the best at us­ing an in­cred­i­bly in­ac­cu­rate spray­can to draw on a wal­l.

There is some­one who can look at a lot full of cars and tell you the log­i­cal or­der to re­move them so they leave in min­i­mum time.

There is some­one who can hit a small bal­l, fly­ing at 150k­m/h with a round stick, 1 out of ev­ery 3 times.

There is some­one who can guess what word goes with al­most ev­ery short def­i­ni­tion.

There is some­one who can tell you all reg­u­lar span­ish verbs that start with T.

There is some­one who knows all about the his­to­ry of jour­nal­ism in Tur­key (I ac­tu­al­ly walked in front of the Mu­se­um of Turk­ish Jour­nal­is­m, and it pains me that I could­n't go at the time).

There is some­one who knows the di­a­log for ev­ery simp­sons episode.

Ev­ery one of those things, and bil­lions more, may be bor­ing to me, but that is sure­ly be­cause I am fail­ing at notic­ing the fun in it, it's a rough­ness of my soul, a fail­ure of my per­cep­tion, a flaw in my vi­sion, which crip­ples me in­to say­ing they are all bor­ing.

Bore­dom is not a sign of su­pe­ri­or­i­ty, it's a sign of in­fe­ri­or­i­ty. Next time you see a bored per­son, some­one that has noth­ing he wants to do, who looks con­de­scend­ing­ly at those who are pas­sion­ate about some­thing, no mat­ter what that may be, feel sad for him.


Contents © 2000-2024 Roberto Alsina