This shows you how to compress and decompress a typical text file using Python module gzip ...

# using module gzip to compress and decompress files
# default compression level is 9 (out of 1-9)
# needs Python27 or higher
# tested with Python27 and Python32  by vegaseat

import gzip

txt_file = "Edictionary.txt"
gz_file = "Edictionary.gz"

# reads in a 747kb .txt file, compresses to a 201kb .gz file
# mode='rb' is needed for the text file
with open(txt_file, 'rb') as f_in:
    with gzip.open(gz_file, 'wb') as f_out:
        f_out.writelines(f_in)

print("Read .gz file in as one string ..")
with gzip.open(gz_file, 'rb') as f:
    # decode <class 'bytes'> to string
    # .decode("utf8") does not work here
    text2 = f.read().decode("latin1")

print("Show first 80 characters:")
print(text2[:80])

print('-'*37)

# a mildly different approach using the class
print("Read .gz file in as list of lines ...")
gzin = gzip.GzipFile(gz_file, 'rb')
lines = gzin.readlines()
gzin.close()

print("Show first 10 lines:")
for line in lines[:10]:
    # decode <class 'bytes'> to string
    line = line.decode("latin1").rstrip()
    print(line)

'''result ...
Read .gz file in as one string ..
Show first 80 characters:
Aachen
aardvark
aardvarks
aaron
abaci
aback
abacus
abacuses
abaft
abalo
-------------------------------------
Read .gz file in as list of lines ...
Show first 10 lines:
Aachen
aardvark
aardvarks
aaron
abaci
aback
abacus
abacuses
abaft
abalone
'''
HiHe commented: great Python code +4

Python comes with module sqlite3 to create and process databases that can be queried with its common query language. First, let's create a database file ...

# explore Python module sqlite3
# create a database file
# the query language is in optional upper case
# using unique id numbers prevents appending an existing db file 
# tested with Python27 and Python32

import sqlite3

# create/connect to a permanent database file
file_name = "stock_portfolio2.db3"
con = sqlite3.connect(file_name)

# establish the cursor
cur = con.cursor()

# if it doesn't exist yet, create the table named stocks
# give each transaction a unique id number
cur.execute('''CREATE TABLE IF NOT EXISTS stocks
    (id INT PRIMARY KEY, date TEXT, trans TEXT, 
    symbol TEXT, qty REAL, price REAL)''')

# insert several lines at once using a
# list of (id, date, trans, symbol, qty, price) tuples
# each tranaction is given a unique id for data security
# the unique id primary key prevents any existing database file
# from being appended with a potentially conflicting data id 
try:
    stocks = [
    (100, '2011-05-07', 'buy', 'AZN', 500, 55.05),
    (101, '2011-05-07', 'buy', 'CAT', 200, 110.34),
    (102, '2011-05-07', 'sell', 'IBM', 100, 168.89),
    (103, '2011-05-07', 'buy', 'GE', 2000, 20.01)
    ]
    # the ? placeholders match tuple items
    cur.executemany("""INSERT INTO stocks
    VALUES (?, ?, ?, ?, ?, ?)""", stocks)
except:
    pass

# commit current data to the db file
con.commit()

# quickly test the database, in sorted order by symbol
cur.execute('SELECT * FROM stocks ORDER BY symbol')
# fetch all data rows
for row in cur.fetchall():
    print(row)

'''
(100, u'2011-05-07', u'buy', u'AZN', 500.0, 55.05)
(101, u'2011-05-07', u'buy', u'CAT', 200.0, 110.34)
(103, u'2011-05-07', u'buy', u'GE', 2000.0, 20.01)
(102, u'2011-05-07', u'sell', u'IBM', 100.0, 168.89)
'''

# done
con.close()

Now let's use the database file we just created ...

# explore Python module sqlite3
# read an existing database file
# query language in upper case (optional)
# tested with Python27 and Python32

import sqlite3

# connect to the permanent database file
file_name = "stock_portfolio2.db3"
con = sqlite3.connect(file_name)

# establish the cursor
cur = con.cursor()

# use cursor method execute() to test the database
cur.execute('SELECT * FROM stocks')
col_name_list = [tup[0] for tup in cur.description]
print("Table header:")
print(col_name_list)

'''
Table header:
['id', 'date', 'trans', 'symbol', 'qty', 'price']
'''

print('-'*50)

cur.execute('SELECT * FROM stocks')
# fetch first data row
row = cur.fetchone()
print(row)

'''result Python32 ...
(100, '2011-05-07', 'buy', 'AZN', 500.0, 55.05)
'''

print('-'*50)

cur.execute('SELECT id FROM stocks')
# fetch id numbers of all data rows
for row in cur.fetchall():
    print(row)

'''
(100,)
(101,)
(102,)
(103,)
'''

print('-'*50)

cur.execute('SELECT trans, qty, symbol, date FROM stocks')
# fetch selected items of all data rows
for row in cur.fetchall():
    print("%s %s %s on %s" % row)

'''
buy 500.0 AZN on 2011-05-07
buy 200.0 CAT on 2011-05-07
sell 100.0 IBM on 2011-05-07
buy 2000.0 GE on 2011-05-07
'''

# done
con.close()

I hope you can dream up a better example of a database.

commented: makes sql look easy +5
commented: easy to understand +13
commented: well done +10

The Python module shelve is used to make a dictionary persistent:

# use a Python dictionary and module shelve
# to create a 'persistent to file' dictionary
# Python2 creates a single (24kb) file 'my_shelve.slv'
# Python3 creates 3 much smaller (1kb) files:
# "my_shelve.slv.dir"
# "my_shelve.slv.dat"
# "my_shelve.slv.bak"

import shelve
import pprint

# name shelve byte stream data file
data_file = "my_shelve.slv"

# save a python dictionary object to a file
# access key will be string 'comp_d'
sh = shelve.open(data_file)
# this will save to the file automatically
sh['comp_d'] = {'upgrade': 'steep hill', 'chip': 'munchies for TV'}

sh.close()

# retrieve the python dictionary object from the file
# use correct access key 'comp_d'
sh = shelve.open(data_file)
dc = sh['comp_d']

# then add additional data
dc['cursor'] = 'someone who swears'
# add to shelve via access key 'comp_d'
# this will update the file too
sh['comp_d'] = dc

sh.close()

# retrieve the updated dictionary from the file and display
sh = shelve.open(data_file)
pprint.pprint(sh['comp_d'])
sh.close()

""" my output -->
{'chip': 'munchies for TV',
 'cursor': 'someone who swears',
 'upgrade': 'steep hill'}
"""

Here we use the module matplotlib to plot a histogram (bar chart) of characters 'a' through 'z' as they appear in a given text ...

# create a list of [char,freq] lists of a text
# the plotting part needs the matplotlib module
# from
# http://sourceforge.net/projects/matplotlib/files/matplotlib/
# Windows installer matplotlib-1.0.1.win32-py2.7.exe
# or for Python32 use
# Windows installer matplotlib-1.1.0.dev.win32-py3.2.exe
# from
# http://www.lfd.uci.edu/~gohlke/pythonlibs/
# tested with Python27 and Python32  by  vegaseat

# use pylab namespace for clarity
import matplotlib.pylab as pylab

# just a simple text for testing
text = """\
Mississippi
"""

alpha = 'abcdefghijklmnopqrstuvwxyz'
# create initial list of [char,freq] lists
# of all lower case characters and freq=0
alpha_freq = [[c, 0]  for c in alpha]

print(alpha_freq)  # test
print('-'*60)

# increment the freq of a given character
for c in text.lower():
    if c in alpha:
        ix = alpha.index(c)
        alpha_freq[ix][1] += 1
        
print(alpha_freq)  # test
print('-'*60)

# use alpha_freq list to plot a char, freq histogram 
# using the matplotlib module's pylab
fig = pylab.figure()
ax = fig.add_subplot(111)
# data points ...
heights = [freq for c, freq in alpha_freq]
values = range(len(alpha))
# draw a matlib bar chart
pylab.bar (values, heights)
pylab.grid (True)
pylab.title ('Letter frequency in a text')
pylab.xlabel ('char a-z')
ax.set_xticks(values)
ax.set_xticklabels(tuple(alpha))
pylab.ylabel ('counts')

pylab.show()

A simpler matplotlib example ...

# plotting with the pylab module from matplotlib
# http://sourceforge.net/projects/matplotlib/files/matplotlib/
# used Windows installer matplotlib-1.0.1.win32-py2.7.exe
# modified Ene's code, tested with Python27

import math
import matplotlib.pylab as pylab

# create the x list data
# arange() is just like range() but allows float numbers
# actually uses numpy's arange()
#
x_list = pylab.arange(0.0, 5.0, 0.01)

# calculate the y list data
#
y_list = []
for x in x_list:
    # give it some fancy decaying function
    y = math.cos(2*math.pi*x) * math.exp(-x)
    y_list.append(y)

pylab.xlabel("x")
pylab.ylabel("cos(2pi * x) * exp(-x)")

# draw the plot with a blue line 'b' (default)
# using x,y data from the x_list and y_list
#
# other drawing styles -->
# 'r' red line, 'g' green line, 'y' yellow line
# 'ro' red dots, 'r.' smaller red dots, 'r+' red pluses
# 'r--' red dashed line, 'g^' green triangles, 'bs' blue squares
# 'rp' red pentagons, 'r1', 'r2', 'r3', 'r4' just check them out
#
pylab.plot(x_list, y_list, 'b')

# optionally save the plot as a .png image file
pylab.savefig('pylab_fancy.png')

# show the pylab plotting window
# zoom the graph, drag the graph, change the margins, save the graph
pylab.show()
commented: works well +10

Something simple, but handy at times ...

# convert an integer number to its binary representation
# and pad the result with a specified number of leading zeros
# tested with Python27 and Python32  by  vegaseat

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    """
    bs = ''
    for x in range(0, bits):
        if 2**x == 2**x & num:
            bs = '1' + bs
        else:
            bs = '0' + bs
    return bs

# testing ...
if __name__ == '__main__':
    print(int2binpad(255, 12))  # 000011111111
    print(int2binpad(254, 12))  # 000011111110
    print(int2binpad(76, 8))    # 01001100
    print(int2binpad(3))        # 0011

Something simple, but handy at times ...

# convert an integer number to its binary representation
# and pad the result with a specified number of leading zeros
# tested with Python27 and Python32  by  vegaseat

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    """
    bs = ''
    for x in range(0, bits):
        if 2**x == 2**x & num:
            bs = '1' + bs
        else:
            bs = '0' + bs
    return bs

# testing ...
if __name__ == '__main__':
    print(int2binpad(255, 12))  # 000011111111
    print(int2binpad(254, 12))  # 000011111110
    print(int2binpad(76, 8))    # 01001100
    print(int2binpad(3))        # 0011

Darn. getting those post duplicates again!

If you have Python 2.7 or higher, vegaseat's approach can be simplified:

# with Python27+ you can use the following scheme for padding
# binary numbers with leading zeros

print(bin(255))                     # 0b11111111
print(bin(255)[2:])                 # 11111111
print(bin(255)[2:].rjust(12, '0'))  # 000011111111

print(bin(76)[2:].rjust(8, '0'))    # 01001100

Or putting it all into one nice function:

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    needs Python27 or higher
    """
    return bin(num)[2:].rjust(bits, '0')

# test
print(int2binpad(255, 12))  # 000011111111
print(int2binpad(254, 12))  # 000011111110
print(int2binpad(76, 8))    # 01001100
print(int2binpad(3))        # 0011

# stressing the function one little, seems to behave
print(int2binpad(76))       # 1001100

Vegaseat surely knows that way, but sometimes people are required not to use bin function but wrap one of their own. If you want to shrink the vegas eater funcition's code to one line it is possible with join and character generator:

# convert an integer number to its binary representation
# and pad the result with a specified number of leading zeros
# tested with Python27 and Python32  by  vegaseat

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    """
    return ''.join('0' if int(num & (2 ** x) > 0) else '1'  for x in reversed(range(0, bits)))

# testing ...
if __name__ == '__main__':
    print(int2binpad(255, 12))  # 000011111111
    print(int2binpad(254, 12))  # 000011111110
    print(int2binpad(76, 8))    # 01001100
    print(int2binpad(3))        # 0011

More traditional style is of course to do division by base and collect modulos in reverse to do generalized version of base change.

If you wan to get numeric input, optionally within a range of values, you can use the Tkinter GUI toolkit (comes with your Python installation) and its small pop-up dialogs in a console program ...

# use Tkinter's simple dialogs (pop-up) to ask for input
# minvalue and maxvalue are optional

try:
    # for Python2
    import Tkinter as tk
    import tkSimpleDialog as tksd
except ImportError:
    # for Python3
    import tkinter as tk
    import tkinter.simpledialog as tksd

root = tk.Tk()
# show input dialogs without the Tkinter window
root.withdraw()

# if a non-numeric value is entered, will prompt again
price = tksd.askfloat("Price", "Enter the price of the item:")
print(price)
# use askfloat or askinteger (whole items only)
quantity = tksd.askinteger("Quantity", "Number of items needed:",
    minvalue=1, maxvalue=1000)
print(quantity)

result = "Total cost is %0.2f" % (price*quantity)
print(result)

# you could even use askstring() to display the result
sf = "%0.2f" % (price*quantity)
tksd.askstring("Result", "Total cost is:", initialvalue=sf)

Questions about threading come up many times on the forum, so here some help ...

# running a function in the background with threading
# apply threading to a function with a function decorator
# without the threading decorator the function counter2
# would tick off first, then the other prints would show

import time
import threading

def background(f):
    """
    a threading decorator
    use @background above the function you want to thread
    (run in the background)
    """
    def bg_f(*a, **kw):
        threading.Thread(target=f, args=a, kwargs=kw).start()
    return bg_f

@background
def counter2(n):
    """show the count every second"""
    for k in range(n):
        print("counting %d" % k)
        time.sleep(1)

# start the counter
counter2(7)
time.sleep(0.9)
print('hello')   # prints hello, before counter prints 1
time.sleep(3)
print('world')   # prints world, before counter prints 4

''' result ...
counting 0
hello
counting 1
counting 2
counting 3
world
counting 4
counting 5
counting 6
'''
commented: now that's easy +5

Thanks a Lot for sharing

Easy to overlook, random.choice() is usually used to pick an item from a list. However, it does apply to any sequence ...

import random

# pick a random letter out of a string
print(random.choice('abcdefg'))

A simple way to display a list of lists/tuples as a table in your browser ...

# make_html_table.py
# create an html table from a data list

def make_html_table(mylist):
    """
    use a list of data tuples and create the html code
    of a html formatted table containing the data items
    """
    rows = ['<td>'+'</td><td>'.join(xx)+'</td>'+'\n' for xx in mylist]
    table = '<table border=2><tr>'
    table += '<tr>'.join(rows)
    table += '</tr></table>'
    return table

# a list of (name, age, weight) tuples (or lists)
# the first tuple is the header
data_list = [
('Name', 'Age', 'Weight'),
('Sarah Gellar', '26', '121'),
('Alec Baldwin', '47', '214'),
('Mandy Moore', '22', '135'),
('Matthew Goode', '29', '167'),
('Amanda Bynes', '19', '112'),
('James Kirk', '24', '175')
]

html_table = make_html_table(data_list)

print(html_table)  # test

# save as html file and show in your browser
with open('html_table.htm', 'w') as fout:
    fout.write(html_table)

You can use this simple code to show the above html file in your web browser ...

# use Python's webbrowser module to show an html code file 

import webbrowser

# open your web browser to run the html file
webbrowser.open('html_table.htm')

The named tuple is a versatile container similar to a tuple but with named indexes replacing the numeric ones ...

# named tuples have named indexes that behave similar to class 
# instances but require no more memory than regular tuples
# tested with Python27 and Python32  by  vegaseat

import collections as co
import pprint

def create_nt_dict(data_list, Person):
    """
    load the named tuple with the data list and
    create a dictionary of the named tuple
    where the instance name is the key
    """
    nt_dict = {}
    for name, age, weight in data_list:
        # use lower first name + initial letter of last name
        # as key to avoid name collisions
        first, last = name.split()
        instance_name = first.lower() + last[0] 
        nt_dict[instance_name] = Person(name, age, weight)       
    return nt_dict   

# a test list of (name, age, weight) tuples
data_list = [
('Sarah Gellar', 26, 121),
('Alec Baldwin', 47, 214),
('Mandy Moore', 22, 135),
('Matthew Goode', 29, 167),
('Amanda Bynes', 19, 112),
('James Kirk', 24, 175)
]

# create the named tuple
# does behave like a Python class so use name 'Person'
Person = co.namedtuple('movie_star', 'name, age, weight')

# load the named tuple and get a dictionary of instances
nt_dict = create_nt_dict(data_list, Person)
# add nt_dict to dictionary local to __main__
locals().update(nt_dict)

# test_prints only ...
pprint.pprint(nt_dict)
print('<>'*35)
pprint.pprint(locals())
print('<>'*35)

# work with the named tuple ...
print("names of instances =\n%s" % sorted(nt_dict.keys()))

'''
names of instances =
['alecB', 'amandaB', 'jamesK', 'mandyM', 'matthewG', 'sarahG']
'''

# pick one instance ...
print(mandyM.name)   # Mandy Moore
print(mandyM.age)    # 22

print('<>'*35)

print("Movie stars under 25 years of age:")
for star in nt_dict:
    star = eval(star)
    if star.age < 25:
        print(star.name, star.age, star.weight)

''' Python32 result ...
Movie stars under 25 years of age:
James Kirk 24 175
Mandy Moore 22 135
Amanda Bynes 19 112
'''
commented: great help +13
# one short look at counters/accumulators
# tested with Python 3.2.1

def xcounter():
    """
    generator function (yield replaces return)
    increments by one each call
    """
    k = 0
    while True:
       k += 1
       yield k

# next is needed with generator functions
# with Python2 use .next
# with Python3 use .__next__
counter = xcounter().__next__
for k in range(5):
    print(counter())

'''
1
2
3
4
5
'''
# one short look at counters/accumulators
# tested with Python 3.2.1

class Count:
    k = 0
    def counter(self):
        self.k += 1
        return self.k
    # this allows you to simply call Count.counter()
    counter = classmethod(counter)

# test ...
for k in range(5):
    print(Count.counter())

'''
1
2
3
4
5
'''

Great thread on Python.... Thanks for sharing.

Looks interesting and fun. Thanks for the introduction vegaseat. If i may ask, what good books would you recommend for starters?

Looks interesting and fun. Thanks for the introduction vegaseat. If i may ask, what good books would you recommend for starters?

How to think like a computer scientist is great for beginners as is Python programming for the absolute beginner. If you already have experience with a programming language head first python and dive into python 3 are also very good.

I have 'how to think like a computer scientist' in my library. Maybe i would start with that then go on to thers.
Thanks

does anybody knows how should I deal with Jython interpreter? it's making me crazy.
where is jython.exe ? where is jython command line?
what about JES?

A quick look at the one line conditional expression:

# using a conditional expression
# tested with Python27 and Python32

y = 1
# written as a common conditional expression
if y == 1:
    x = 5
else:
    x = 3
print( "if y = %d then x = %d" % (y, x ) )

print("--- using one-line conditional expression ---")

# can be written as a one-line conditional expression
x = 5 if y == 1 else 3
print( "if y = %d then x = %d" % (y, x ) )

y = 77
x = 5 if y == 1 else 3
print( "if y = %d then x = %d" % (y, x ) )

"""my result -->
if y = 1 then x = 5
--- using one-line conditional expression ---
if y = 1 then x = 5
if y = 77 then x = 3
"""

I am using the Eric5 Python IDE that allows you to test your code with different versions of Python.
Under Preferences I set the Debugger to use Python27 for code with extension .py2

Print 10 numbers per row:

# avoids print(),
# works with Python2 and Python3

import sys

for k in range(100):
    # print 10 numbers per row
    # ('\t', '\n')[k % 10 == 9] selects '\t' or '\n'
    str1 = "%3d%s" % (k, ('\t', '\n')[k % 10 == 9])
    sys.stdout.write(str1)
    sys.stdout.flush()

print('-'*40)  # 40 dashes, cosmetic

for k in range(100):
    # print 10 numbers per row
    # use one-line conditional if/else
    str1 = "%3d%s" % (k, ('\n' if k % 10 == 9 else '\t'))
    sys.stdout.write(str1)
    sys.stdout.flush()

'''my output >>>
  0   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  32  33  34  35  36  37  38  39
 40  41  42  43  44  45  46  47  48  49
 50  51  52  53  54  55  56  57  58  59
 60  61  62  63  64  65  66  67  68  69
 70  71  72  73  74  75  76  77  78  79
 80  81  82  83  84  85  86  87  88  89
 90  91  92  93  94  95  96  97  98  99
----------------------------------------
  0   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  32  33  34  35  36  37  38  39
 40  41  42  43  44  45  46  47  48  49
 50  51  52  53  54  55  56  57  58  59
 60  61  62  63  64  65  66  67  68  69
 70  71  72  73  74  75  76  77  78  79
 80  81  82  83  84  85  86  87  88  89
 90  91  92  93  94  95  96  97  98  99
'''
# create an acronym

str1 = "Senior health inFormation development"

# just in case it isn't all lower case
str2 = str1.lower()

# make a title-cased copy
str3 = str2.title()

# now build the acronym from the capitalized letters
str4 = ""
for char in str3:
    if char.isupper():
        str4 += char

print("Original string : %s" % str1)
print("All lower case  : %s" % str2)
print("All words titled: %s" % str3)
print("Simple acronym  : %s" % str4)

'''
Original string : Senior health inFormation development
All lower case  : senior health information development
All words titled: Senior Health Information Development
Simple acronym  : SHID
'''
# bubble sort a list in either direction

def bubblesort2(q):
    """
    test the bubble sort of a list of numbers
    returns asc and des lists
    asc is the list in ascending order
    des is the list in descending order
    """
    # make copies of the list
    asc = list(q)
    des = list(q)
    for passes in range(len(q)-1, 0, -1):
        for index in range(passes):
            # ascending order
            if asc[index] > asc[index + 1]:
                # do a tuple swap
                asc[index], asc[index + 1] = asc[index + 1], asc[index]
            # descending order
            if des[index] < des[index + 1]:
                des[index], des[index + 1] = des[index + 1], des[index]
    return asc, des

mylist = [4, 2, 7, 9, 25]
asc_list, des_list = bubblesort2(mylist)

print("original  : %s" % mylist)
print("ascending : %s" % asc_list)
print("descending: %s" % des_list)

'''
original  : [4, 2, 7, 9, 25]
ascending : [2, 4, 7, 9, 25]
descending: [25, 9, 7, 4, 2]
'''

@ZZucker:
I would like to point out that the code snippet of mine http://www.daniweb.com/software-development/python/code/422450/input-generator has use case example allmost same as ZZucker first example, as it capitalizes first letters of each word (as title casing does), just join the first letter of words instead of list of capitalized words.

The buble sort in two orders I do not like so much, because the second list is just reverse of other one and completely redundant. I also like to keep index play in minimum, here is my bubble sort for comparison

def bubble(seq):
    seq = seq[:]
    for thisfar in reversed(range(len(seq))):
        done = True
        for pos in range(thisfar):
            if seq[pos] > seq[pos+1]:
                seq[pos], seq[pos+1] = seq[pos+1], seq[pos]
                done = False
        if done:
            #print thisfar
            return seq
# everyone likes TGIF
# so loop through a whole year day by day and show all the dates that are Fridays

import datetime

# pick a year
year = 2012

# create date objects
begin_year = datetime.date(year, 1, 1)
end_year = datetime.date(year, 12, 31)
one_day = datetime.timedelta(days=1)

print("These are all the Fridays of %d:" % year)
next_day = begin_year
for day in range(0, 366):
    if next_day > end_year:
        break
    # week starts with monday = 0, so friday = 4
    if next_day.weekday() == 4:
        print("%s is a Friday" % next_day)
    # increment date object by one day
    next_day += one_day
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.