Skip to main content

Ralsina.Me — Roberto Alsina's website

PyQt Quickie: command line parsing

So, you are writ­ing a PyQt ap­p, and you want it to sup­port com­mand line ar­gu­ments. So you do some­thing like this:

opt_parser = OptionParser()
opt_parser.add_option("-q", dest="quickly", action="store_true",
    help="Do it quickly (default=False)")
(options, args) = opt_parser.parse_args(sys.argv)
app = QApplication(sys.argv)
:
:
:

Or maybe even QAp­pli­ca­tion([]). Ok, you are doing it wrong. And this is wrong in most tutorials, too. Why? Because Qt (and thus PyQt) supports a bunch of useful command line options already. So if you do it like in the first listing, and pass "-style=oxygen" or whatever, one of the following will happen.

  1. Op­t­­Pars­er is go­ing to tell you it's not a valid op­­tion and abort

  2. You will ig­nore the op­­tion and not do any­thing use­­ful with it

  3. You will have your own -style op­­tion and do two things with it

All three out­comes are less than ide­al.

The right way to do this is:

opt_parser = OptionParser()
opt_parser.add_option("-q", dest="quickly", action="store_true",
    help="Do it quickly (default=False)")
app = QApplication(sys.argv)
(options, args) = opt_parser.parse_args(app.arguments())
:
:
:

This way, you give PyQt a chance to process the options it recognizes, and, then, you get to handle the rest, because app.arguments() has all Qt options removed.

The bad side of this is, you will make --help slightly slower, since it will have to build a QApplication to do nothing, and you will have undocumented options. Solution for both problems left as an exercise.

The Lowly Symbols

Two nights ago, I was at a birth­day par­ty. In it, some­one (name pre­served be­cause you don't know the guy) said some­thing like "sym­bols are use­ful to ral­ly peo­ple for a fight­".

I an­swered "if I ev­er need to ral­ly peo­ple to a fight, I would make sure to choose some un­cool sym­bol (maybe a naked mole rat, ram­pan­t), so I at least know they are there be­cause they un­der­stand the is­sue, and not be­cause of cool mar­ket­ing". Which is prob­a­bly a pret­ty stupid thing to say, but:

  1. I was on my 3rd fer­­net

  2. I was trolling the oth­­er guy

  3. Fer­­net troll is drunk

  4. I kin­­da be­lieve it

It's stupid be­cause on­ly ac­cept­ing the help of true be­liev­ers and not ac­tive­ly try­ing to make peo­ple be­lieve are good ways to en­sure you have a very mo­ti­vat­ed tiny mi­nor­i­ty on your side (Lin­ux Year of The Desk­top anal­o­gy ges here).

But I kin­da be­lieve it any­way, be­cause be­ing ug­ly and loved is warmer than be­ing pret­ty and loved, be­cause be­ing dif­fi­cult and ap­pre­ci­at­ed is more valu­able than be­ing ac­ces­si­ble and liked. But that on­ly works if you are tru­ly dif­fi­cult, and not in­ten­tion­al­ly so, that's just be­ing a poseur. And tru­ly ug­ly, not Char­l­ize-Theron-on-­fat-­make­up ug­ly.

So, to what point is any of us hon­est­ly an­noy­ing? That, friend­s, is the is­sue here. And if I ev­er have to lead oth­ers in­to some­thing, I hope I do it as my­self, and they come be­cause of a rea­son that is theirs and not mine.

I am not here to con­vince peo­ple. I am here to know peo­ple.

Six Years

casamiento

And she's still here.

Scraping doesn't hurt

I am in gen­er­al al­ler­gic to HTM­L, spe­cial­ly when it comes to pars­ing it. How­ev­er, ev­ery now and then some­thing comes up and it's fun to keep the mus­cles stretched.

So, con­sid­er the Ted Talks site. They have a re­al­ly nice ta­ble with in­for­ma­tion about their talk­s, just in case you want to do some­thing with them.

But how do you get that in­for­ma­tion? By scrap­ing it. And what's an easy way to do it? By us­ing Python and Beau­ti­ful­Soup:

from BeautifulSoup import BeautifulSoup
import urllib

# Read the whole page.
data = urllib.urlopen('http://www.ted.com/talks/quick-list').read()
# Parse it
soup = BeautifulSoup(data)

# Find the table with the data
table = soup.findAll('table', attrs= {"class": "downloads notranslate"})[0]
# Get the rows, skip the first one
rows = table.findAll('tr')[1:]

items = []
# For each row, get the data
# And store it somewhere
for row in rows:
    cells = row.findAll('td')
    item = {}
    item['date'] = cells[0].text
    item['event'] = cells[1].text
    item['title'] = cells[2].text
    item['duration'] = cells[3].text
    item['links'] = [a['href'] for a in cells[4].findAll('a')]
    items.append(item)

And that's it! Sur­pris­ing­ly pain-free!


Contents © 2000-2023 Roberto Alsina