Archive

Archive for the ‘python’ Category

Countdown in command line

December 8, 2012 Leave a comment

I have a console application that runs in an eternal loop. It does something then it sleeps for 5 minutes. How to do this pause in a nice way?

(1) time.sleep(300)

The first idea is to put it to sleep for 5 minutes. It does the job but when I check the output of the script, I have no idea when it continues. So it’s not very informative.

(2) print a dot each second

Another way is to print a dot each second. If you use sys.stdout.write('.'), then don’t forget to set the output unbuffered. It’s a bit better but still not perfect.

(3) countdown

The nicest way may be a countdown that goes from 300 down to 0. Now, you don’t want to print each number in a new line, do you? How to keep the countdown in the same line?

#!/usr/bin/python2.7 -u
# -u switch: unbuffered output

def wait(sec):
    while sec > 0:
        sys.stdout.write(str(sec) + '     \r')
        sec -= 1
        time.sleep(1)

The trick is the ‘\r‘, which means “carriage return”. That is: print the number, clear with some spaces, then jump back to the beginning of the line.

Nice, but… How to get rid of the cursor? You can switch it off/on in Linux easily. Here is my complete solution:

#!/usr/bin/python2.7 -u

import os
import sys
from time import sleep

def wait(sec):
    while sec > 0:
        sys.stdout.write(str(sec) + '     \r')
        sec -= 1
        sleep(1)
        
def main():
    os.system('setterm -cursor off')
    try:
        while True:
            # an external command that I call regularly
            os.system('./proxies.py')
            wait(300)
    except KeyboardInterrupt:
        print
    finally:
        os.system('setterm -cursor on')

############################################ 

if __name__ == "__main__":
    main()

The finally part makes sure that the cursor will be switched back on, even if the script is interrupted with CTRL+C for instance.

The same idea in a more elegant way:

class CursorOff(object):
    def __enter__(self):
        os.system('setterm -cursor off')
        
    def __exit__(self, *args):
        os.system('setterm -cursor on')

def wait(sec):
    while sec > 0:
        sys.stdout.write(str(sec) + '     \r')
        sec -= 1
        try:
            sleep(1)
        except KeyboardInterrupt:
            print
            return

with CursorOff():
    wait(3)

I put it in a module that you can find in my jabbapylib library, here.

Terminate a script after X seconds

December 8, 2012 Leave a comment

Problem
In Qt, there is a class called QTimer. With QTimer you can, for instance, terminate your application in X seconds. Example:

#!/usr/bin/env python

import sys

from PySide.QtCore import *
from PySide.QtGui import *

SEC = 1000    # 1 sec. is 1000 msec.

def main():
    app = QApplication(sys.argv)
    form = QDialog()
    form.show()
    # suicide in 3 seconds:
    QTimer.singleShot(3 * SEC, app.quit)
    app.exec_()

if __name__ == "__main__":
   main()

Question: how to have the same effect in a command-line application?

Solution
I came up with the following solution:

#!/usr/bin/env python

import sys
from time import sleep
import signal

class MyTimer(object):
    """
    Similar to Qt's QTimer. Call a function in a specified time.

    Time is given in sec. Usage:
    mt = MyTimer()
    mt.singleShot(<sec>, <function_name>)

    After setting it, you can still disable it:
    mt.disable()

    If you call it several times, any previously scheduled alarm
    will be canceled (only one alarm can be scheduled at any time).
    """
    def singleShot(self, sec, func):
        self.f = func
        signal.signal(signal.SIGALRM, self.handler)
        signal.alarm(sec)

    def handler(self, *args):
        self.f()

    def disable(self):
        signal.alarm(0)

def main():
    while True:
        print '.',
        sleep(0.5)
        
if __name__ == "__main__":
    mt = MyTimer()
    mt.singleShot(3, sys.exit)
    main()

As can be seen, the main function has an eternal loop. However, this program will terminate in 3 seconds. I’m imitating QTimer’s singleshot. The differences: (1) you must create a MyTimer object, and (2) time is given in seconds, not in milliseconds. You can also write it in one line if you want: MyTimer().singleShot(3, sys.exit).

It is written in a general form, so instead of sys.exit, you can also call a different function.

Raise a timeout exception after X seconds

December 8, 2012 Leave a comment

Problem
You make a call that may stuck (for instance downloading a webpage). How to timeout after some time?

Solution
I found the following tip at http://stackoverflow.com/questions/8464391 (Unix only):

import signal
import time

def test_request(arg=None):
    """Your http request."""
    time.sleep(2)
    return arg

class Timeout():
    """Timeout class using ALARM signal."""
    class Timeout(Exception):
        pass

    def __init__(self, sec):
        self.sec = sec

    def __enter__(self):
        signal.signal(signal.SIGALRM, self.raise_timeout)
        signal.alarm(self.sec)

    def __exit__(self, *args):
        signal.alarm(0)    # disable alarm

    def raise_timeout(self, *args):
        raise Timeout.Timeout()

def main():
    # Run block of code with timeouts
    try:
        with Timeout(3):
            print test_request("Request 1")
        with Timeout(1):
            print test_request("Request 2")
    except Timeout.Timeout:
        print "Timeout"

#############################################################################

if __name__ == "__main__":
    main()

Note that time for signal.alarm must be specified in seconds (integer value).

Output:

Request 1
Timeout
Categories: python Tags: , , ,

Eclipse-PyDev on steroids: Aptana Studio

December 7, 2012 2 comments

aptanaYesterday I tried Aptana Studio 3 and I’m impressed. My preferred IDE was Eclipe with the PyDev plugin. The good news is Aptana Studio is built on Eclipe, but it contains lots of useful plugins preinstalled (PyDev is among them). So it feels like a tuned up Eclipse :)

I think I will use Aptana from now on for larger projects. And it’s free, of course.

A course on Udemy about Python GUI programming with Qt

December 4, 2012 Leave a comment
Categories: python Tags: , , , ,

Writing non-ASCII text to file

December 2, 2012 2 comments

Problem
You download the source of an HTML page in a string and you want to save it in a file. However, you get some UnicodeDecodeError :(

Solution

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

Here is how to read it back:

f = open('test', 'r')
print f.read().decode('utf8')

This tip is from here.

Python PIL : IOError: decoder jpeg not available

December 2, 2012 Leave a comment

Problem
Working with JPG files, PIL drops the following error:

Python PIL : IOError: decoder jpeg not available

Solution

sudo pip uninstall PIL
sudo apt-get install libjpeg8-dev
sudo pip install PIL

Found here.

Categories: python Tags: , , , ,

Install a package via pip even if PyPI is down

December 2, 2012 Leave a comment

Problem
PyPI is down but still, you want to install a package.

Solution
Use a mirror, e.g. Create.io:

sudo pip install -i http://simple.crate.io/ <package_name>
Categories: python Tags: , , , ,

Write Python inside Bash

November 24, 2012 2 comments

Problem
You want to embed Python code inside a Bash script.

Solution
Here is a possible solution:

#!/usr/bin/bash

# name.sh

# Example:
# Write a bash script that has one parameter: your name.
# It prints every second character of your name.

TFILE="`basename $0`.$$.py"

cat <<END >$TFILE
#!/usr/bin/env python

import re
import sys

bash_name = re.sub(r'\.\d+\.py', '', sys.argv[0])

def process(s):
    print s[::2]

def main():
    if len(sys.argv) > 1:
        process(sys.argv[1])
    else:
        print "Usage: {0} <parameter>".format(bash_name)

if __name__ == "__main__":
    main()
END

chmod u+x $TFILE
./$TFILE "$@"
/bin/rm $TFILE

Usage:

./name.sh Your_Name
Yu_ae    # output
Categories: fun, python Tags: ,

Handle CTRL+C in your script

November 21, 2012 Leave a comment

Question

In your script you want to handle the SIGINT signal, i.e. when the user wants to stop the script with CTRL+C, you want to call a function to handle the situation.

Answer

Here is an example:

#!/usr/bin/env python

import signal
import time

def sigint_handler(signum, frame):
    print 'Stop pressing the CTRL+C!'

signal.signal(signal.SIGINT, sigint_handler)

def main():
    while True:
       print '.'
       time.sleep(1)

##########

if __name__ == "__main__":
    main()

Now the script is immune against CTRL+C. You will have to kill it (“kill <PID>”) if you want to stop it.

If you want protection against “kill <PID>”, handle the SIGTERM signal too :)

Design a site like this with WordPress.com
Get started