Tag Archives: python

Building and Packaging a Python command-line tool for Debian

python-logo-notext-svg

Python packaging has a chequered past.

Distutils was and still is the original tool included with the standard library. But then setuptools was created to overcome the limitations of distutils, gained wide adoption, subsequently stagnated, and a fork called distribute was created to address some of the issues. Distutils2 was an attempt to take the best of previous tools to support Python 3, but it failed. Then distribute grew to support Python 3, was merged back in to setuptools, and everything else became moot!

Unfortunately, it’s hard to find reliable information on python packaging, because many articles you might find in a Duckduckgo search were created before setuptools was reinvigorated. Many reflect practices that are sub-optimal today, and I would disregard anything written before the distribute merge, which happened in March 2013.

Continue reading

Streaming JSON with Flask

Update March 2021

This post still gets a fair few hits, so I want to preface this by saying that I wrote this some time ago, and probably wouldn’t do the same thing today. The main problem is that I ignored the client! Sending a single whole JSON object in such a way means the client has to reassemble the whole thing in-memory anyway, which somewhat defeats the point, unless you have fat clients and very thin servers (or processing is slow and you have a very short socket timeout). You might have a valid use-case for a hack like this, but if I were to solve this problem again, I’d send newline-delimited json instead (with metadata in headers or on a separate endpoint if necessary).

I have a SQLAlchemy query (able to behave as an iterator) which could return a large result set. First version of the code was very simple. Release objects have a to_dict() function which returns a dictionary, so I append to a list and jsonify the result:

# releases = <SQLAlchemy query object>

output = []
for r in releases:
    output.append(r.to_dict())

return jsonify(releases=output), 200

(context on github)

This result set could potentially grow to a point that fitting it memory would be impractical – with only a thousand releases there is already a significant lag before we start getting results. Continue reading

Pausing Spotify and playing a random video in Python – A party trick for Halloween

For a Halloween party last weekend I wrote a python script to pause Spotify, play a random video and start music playback again. The videos were basic ogg files I cobbled together which showed a scary image and evil laughs or screaming with OpenShot. I can’t really share them, as I don’t have rights to the media, but it’s pretty simple to recreate them yourself.

The code for this script is on Github, and I’ve reproduced the latest snapshot below. Feel free to fork and improve if you want to scare your guests, or add support for other OS’s. Presently it only supports Linux because I used dbus to perform the play/pause actions.

[python]
#!/usr/bin/python

”’
This is a Halloween party script which pauses Spotify and plays a video
at random intervals.
”’

import random
import subprocess
from subprocess import call
from time import sleep
import os
import datetime

start_time = datetime.time(21, 0, 0)
stop_time = datetime.time(23, 0, 0)

video_dir = ‘/home/alex/Videos/scream/’
videos = { ‘scream1_nofade.ogg’: 30,
‘happy.ogg’: 1,
‘evil_laugh.ogg’: 5,
}

def time_in_range(start, end, x):
“””Return true if x is in the range [start, end]”””
if start <= end:
print(“start<end”)
return start <= x <= end
else:
print(“end<start”)
return start <= x or x <= end

def weighted_choice(weights):
total = sum(weights for video in weights)
r = random.uniform(0, total)
upto = 0
print(“total: %s\nrandom: %s” % (total, r))

for video in weights:
w = weights
if upto + w > r:
return video
upto += w
assert False, “shouldn’t get here”

def spotifyPause():
command = “dbus-send –print-reply –dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Pause”
print(“pausing spotify”)
os.system(command)

def spotifyPlay():
print(“playing spotify”)
command = “dbus-send –print-reply –dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause”
os.system(command)

def play_video(video_file):
print(“Playing %s” % video_file)
#call([‘/usr/bin/mplayer’, ‘-fs’, video_file], stdout=None, stderr=None)
#result = subprocess.Popen([‘/usr/bin/mplayer’, ‘-really-quiet’, ‘-fs’, video_file])
result = subprocess.check_call([‘/usr/bin/mplayer’, ‘-really-quiet’, ‘-fs’, video_file], stdout=None, stderr=None)
return result

def playBuzz(buzzfile):
print(“Buzz…”)
result = subprocess.check_call([‘/usr/bin/mplayer’, ‘-really-quiet’, ‘-ss’, ’18’, buzzfile], stdout=None, stderr=None)
return result

def infiniteLoop():
while 1:
current_time = datetime.datetime.now().time()
#if current_time > stop_time or current_time < midday:

choice = weighted_choice(videos)

random_time = random.randrange(1200,2400)
random_time = 3

video_file = video_dir + choice
print(“Chose video %s after %s seconds” % (video_file, random_time))
sleep(random_time)

# Whether to play buzz
buzz = False
if random.randrange(0,100) > 90:
buzz = True

# Continue if outside time range
if not time_in_range(start_time, stop_time, current_time):
print(“Not playing video, outside time range”)
continue

# Do it
spotifyPause()
if buzz:
playBuzz(‘/home/alex/Videos/scream/audio/buzz.mp3’)
play_video(video_file)
spotifyPlay()

if __name__ == “__main__”:
infiniteLoop()
[/python]

Calling mysqldump in Python

Python is a fantastic tool to know, and despite being a beginner I find myself using it more and more for everyday tasks. Bash is great for knocking together quick scripts, but when you want to something a little more complex such as interfacing with APIs or other systems over a network, you really need a more fully-featured programming language.

The topic of this post, however, is the kind of task that bash is perfect for. Thanks to mysqldump, a database backup script can be written in a few lines and dump/restores are easily automated. So why on earth would we do this in Python?
Continue reading