Posts tagged ‘Python’

Excel und Python Win32COM

Hier ein kleines Beispiel, wie man mittels COM eine Excel-Mappe aus Python heraus befüllt und die Excel-Instanz beendet.

from win32com import client
 
# http://stackoverflow.com/questions/10221150/cant-close-excel-completely-using-win32com-on-python
def close_excel_by_force(excel):
    import win32process
    import win32gui
    import win32api
    import win32con
    import time
 
    # Get the window's process id's
    hwnd = excel.Hwnd
    t, p = win32process.GetWindowThreadProcessId(hwnd)
    # Ask window nicely to close
    win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
    # Allow some time for app to close
    time.sleep(10)
    # If the application didn't close, force close
    try:
        handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, p)
        if handle:
            win32api.TerminateProcess(handle, 0)
            win32api.CloseHandle(handle)
    except:
        pass
 
# Öffne Referenz zu Excel
excel = client.Dispatch("Excel.Application")
 
# Wir wollen sehen, was geschieht
excel.Visible= True
 
# Öffne eine bestehende Arbeitsmappe (im selben Verzeichnis)
wb = excel.Workbooks.Open('C:/Users/john/doe/win32test.xlsx')
 
# Wähle das erste Arbeitsblatt aus
ws = wb.Worksheets(1)
 
# Wähle alle Zellen aus
excel.Cells.Select()
# Entferne den Zellschutz
excel.Selection.Locked = False
# Wähle die Spalten B bis E aus
excel.Range("B:E").Select()
# setze den Zellschutz
excel.Selection.Locked = True
 
# Schütze das Sheet mit einem Passwort
ws.Protect("password", True, True)
 
# Speichere ab
wb.Save()
 
# Schließe die Mappe
wb.Close()
 
# Close Excel
excel.Quit()
wb = None
wbs = None
 
close_excel_by_force(excel)

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Checking TeX files for cite-errors

Today I had to TeX a longer file with numerous \cite[somestuff]{citekey} sequences, of which some had hard-to-spot errors (some ‚]‘ were missing). The following Python script checks if each \cite command has matching '[]' and '{}' sequences. I’ll probably extend this script to accept simple \cite{citekey} sequences that have no optional parameter.

#!/usr/bin/python
import re
 
with open('filetocheck.tex') as f:
	content = f.readlines()
 
index = 0
 
for a in content:
	index = index + 1
	if "cite"  in a: # check only lines that contain 'cite'
		matches = re.search(r'(.*)\[(.*)\]\{(.*)\}',a) # search for <sometext>[<sometext>]{<sometext>}
		if not matches:
			print (">>> Fail in row" , str(index), a)

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Using Python to compute a MD5 Hash

This entry is part 3 of 4 in the series MD 5 Calculation

Here some Python code to calculate the MD5 hash for a given file:

# from http://www.pythoncentral.io/hashing-files-with-python/
import hashlib
 
hasher = hashlib.md5()
with open('e:/Mappe1.xlsx', 'rb') as afile:
    buf = afile.read()
    hasher.update(buf)
print(hasher.hexdigest())

Here the final script that provides the same functionality as the Powershell script I posted earlier today:

# http://www.pythoncentral.io/hashing-files-with-python/
import hashlib
import os
import codecs
 
hasher = hashlib.md5()
 
def calcHash(filename):
	print("Filename:   " + filename)
	with open(filename, 'rb') as afile:
		buf = afile.read()
		hasher.update(buf)
		print("Calculated: " + hasher.hexdigest())
		md5file = (os.path.splitext(filename)[0]) + ".md5"
		givenMD5 = codecs.open(md5file, "r", "utf-8-sig")
		print("Provided:   " + str(givenMD5.read()).lower())
 
calcHash("e:/Mappe1.xlsx")

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Accessing FTP servers with Python

Here’s a short code sample how to list a remote directory via FTP.

from ftplib import FTP
 
ftp = FTP('server')
ftp.connect()
ftp.login('user','password')                    
ftp.cwd('folder')              
ftp.dir()
ftp.quit()

Hier noch der passende Code für den Upload von Dateien:

import ftplib
import os
 
def upload(ftp, file):
    ext = os.path.splitext(file)[1]
    print("Putting ", file)
    if ext in (".txt", ".htm", ".html" , ".tex"):
        ftp.storlines('STOR ' + file, open(file,'rb'))
    else:
        ftp.storbinary('STOR ' + file, open(file,'rb'))
 
ftp = ftplib.FTP("remoteserver")
ftp.login("user", "password")
 
upload(ftp, "index.html")

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Generating math exercises for kids with LuaLaTeX

Arno T. has sent me a nice piece of LuaLaTeX code that does more or less the same thing as my Python code. I guess, I should have a closer look at LuaLaTeX.

\documentclass{scrartcl}
\usepackage{booktabs}
\usepackage{luacode}
\usepackage{longtable}
 
\begin{document}
\begin{longtable}{rcrcl}
\toprule
\luaexec{
function round(num, idp)
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult
end
random = math.random
tp = tex.print
%
min = 1
max = 10
math.randomseed(os.time())
for i = 1,20 do
a = random(min,max)
b = random(min,max)
op = random(1,4)
if (op==1) then
c = a+b
tp(a.."&+&"..b.."&=&"..c.."\\\\")
elseif (op==2) then
c = a-b
tp(a.."&-&"..b.."&=&"..c.."\\\\")
elseif (op==3) then
c = a*b
tp(a.."&*&"..b.."&=&"..c.."\\\\")
elseif (op==4) then
c = a/b
tp(a.."&/&"..b.."&=&"..round(c,3).."\\\\")
end
end
tex.print("\\bottomrule")
}
\end{longtable}
\end{document}

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Generating math exercises for kids

Here’s a simple Python script which generates math exercises for kids. It uses the Century Schoolbook font which is said to be well readable and LaTeX’s longtable. I just ran some tests, generating 24’000 lines on 2000 pages was no deal at all.

#!/usr/bin/python
# coding: utf-8
import random
import os
 
min = 1 # number to start with
max = 10 # maximum number
count = 24 # 12 fit on one page
 
with open('Aufgaben.tex', 'w') as texfile:
	texfile.write("\\documentclass[15pt,ngerman]{scrartcl}\n")
	texfile.write("\\usepackage[utf8]{inputenc}\n")
	texfile.write("\\usepackage{tgschola,longtable}\n")
	texfile.write("\\usepackage[T1]{fontenc}\n")
	texfile.write("\\setlength{\\parindent}{0pt}\n")
	texfile.write("\\pagestyle{empty}\n")
	texfile.write("\\renewcommand*{\\arraystretch}{1.5}\n")
	texfile.write("\\begin{document}\n")
	texfile.write("\\huge\n")
	texfile.write("\\begin{longtable}{cccp{8cm}c}")
 
	for i in range(count):
		a = random.randint(min, max)
		b = random.randint(min, max)
 
		result = a + b;
 
		texfile.write('%s &+ &%s &= &%s \\\\ \\hline\n'%(str(a),str(b),str(result)))
 
	texfile.write("\\end{longtable}\n")
	texfile.write("\\end{document}\n")
 
os.system("pdflatex Aufgaben.tex")
os.startfile("Aufgaben.pdf") # this line may not work under Linux

With little modification one can also generate substraction exercises:

#!/usr/bin/python
# coding: utf-8
import random
 
min = 1
max = 12
count = 24
 
import os # for sys calls
 
with open('Aufgaben.tex', 'w') as texfile:
	texfile.write("\\documentclass[15pt,ngerman]{scrartcl}\n")
	texfile.write("\\usepackage[utf8]{inputenc}\n")
	texfile.write("\\usepackage{tgschola,nicefrac,longtable}\n")
	texfile.write("\\usepackage[T1]{fontenc}\n")
	texfile.write("\\setlength{\\parindent}{0pt}\n")
	texfile.write("\\pagestyle{empty}\n")
	texfile.write("\\renewcommand*{\\arraystretch}{1.5}\n")
	texfile.write("\\begin{document}\n")
	texfile.write("\\huge\n")
	texfile.write("\\begin{longtable}{cccp{8cm}c}")
 
	for i in range(count):
		b = random.randint(min, max)
		a =  b + random.randint(1, 9)
 
		result = a - b;
 
		texfile.write('%s &- &%s &= &%s \\\\ \\hline\n'%(str(a),str(b),str(result)))
 
	texfile.write("\\end{longtable}\n")
	texfile.write("\\end{document}\n")
 
os.system("pdflatex Aufgaben.tex")
os.startfile("Aufgaben.pdf")

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Beispiel für eine MySQL Funktion

Ich bereite momentan die Spendenquittungen der Dingfabrik mit Python, Jinja2, MySQL und LaTeX auf. Um den SQL Code sauber zu halten, lagere ich einiges aus dem Python-Code in MySQL Funktionen aus.

Hier ein einfaches Beispiel, das basierend auf Parametern für Mitglieds-ID und Namenstyp entweder der Vornamen, Nachnamen oder kompletten Namen eines Mitglieds zurückgibt.

DROP FUNCTION IF EXISTS fs_getname;
DELIMITER $$
CREATE FUNCTION fs_getname(nummer INT, typ CHAR)
 RETURNS VARCHAR(100)
 NOT DETERMINISTIC
 BEGIN
	IF typ = 'c' THEN
		RETURN (SELECT TRIM(CONCAT(COALESCE(Vorname,"")," ",COALESCE(Name," "))) FROM Stammdaten WHERE  ID = nummer);
	ELSEIF typ = 'f' THEN
		RETURN (SELECT COALESCE(Vorname,"") FROM Stammdaten WHERE  ID = nummer);
	ELSEIF typ = 'l' THEN
		RETURN (SELECT COALESCE(Name,"") FROM Stammdaten WHERE  ID = nummer);		
	END IF;
END$$
DELIMITER ;

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Kalenderwochen erzeugen mit Python

Basierend auf einem Kommentar zu http://code.activestate.com/recipes/521915-start-date-and-end-date-of-given-week/ hier ein kurzer Code-Schnipsel, der die Anfangs- und Endtage aller Kalenderwochen in 2014 ausspuckt.

from datetime import date, timedelta
 
def get_week_days(year, week):
    d = date(year,1,1)
    if(d.weekday()>3):
        d = d+timedelta(7-d.weekday())
    else:
        d = d - timedelta(d.weekday())
    dlt = timedelta(days = (week-1)*7)
    return d + dlt,  d + dlt + timedelta(days=6)
 
for x in range(1, 54):
	a,b = get_week_days(2014,x);
	print ("\\subsection{" + a.strftime('%d.%m.%Y') + " -- " +  b.strftime('%d.%m.%Y') + "}\n\n\n");

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Rolling dice with Python / Würfeln mit Python

Als kleines Projekt, um etwas mehr in Python einzusteigen, habe ich mir eine Simulation von „Mensch ärgere dich nicht“ überlegt.

Dazu hier ein kleines Skript, das würfelt und dabei auch beachtet, dass bei einer ‚6‘ mehrfach gewürfelt wird. Eine Test-Funktion ist auch dabei, die relativen Häufigkeiten stimmen mit meinen gedachten Werten überein, es scheint also zu funktionieren.

# for the random selection
from random import choice
# to create the sorted dictionary
import collections
 
 
# if throwDice() is called without param, assume that summed equals 0 
# used when player rolls a '6'
def throwDice(*args):
	if not args: 
		summed = 0
	else:
		summed = args[0]
	# roll the dice
	x = choice(range(1,7))
	# if '6' was rolled, we roll again until x <> 6 is rolled
	if x == 6:
		return throwDice(summed+6)	
	else:
	# if no '6' was rolled in *this* run, we just return the aggregated number	
		return summed+x
 
# little test function to get the absolute frequencies
def TestDice(n):
	# create a dictionary
	d = {}
	for x in range(0, n):
		# roll the dice
		wurf = throwDice()	
 
		# if key is found, just increase its frequency by 1 
		if wurf in d:
			d.update({wurf:d[wurf]+1})
		else:
			# else create new key with initiL frequency 1 
			d.update({wurf:1})
	od = collections.OrderedDict(sorted(d.items()))
	for k, v in od.iteritems(): 
		print k, v
 
TestDice(6000)

English summary: some code to roll dice with Python. The frequencies are consistent with the expected values so it seems to be correct.

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website

Programming Post-Commit Hooks for Subversion with Python

I am a regular user of Subversion, all my important TeX files are stored in a SVN repository. SVN has a few builtin hooks, which means at certain events certain scripts are called. The following templates can be found in the hooks subdirectory of the server repository:

  • post-commit.tmpl
  • post-lock.tmpl
  • post-revprop-change.tmpl
  • post-unlock.tmpl
  • pre-commit.tmpl
  • pre-lock.tmpl
  • pre-revprop-change.tmpl
  • pre-unlock.tmpl
  • start-commit.tmpl

It does not matter in what kind of language the scripts are written, Subversion only cares if an executable script (or *.exe file with this name) is present (remove ‚.tmpl‘ at the end of a script to activate it). Today, after reading http://palita.net/2011/08/24/svn-hooks-automatischer-checkout-nach-commits/, I was interested in writing a small Python script which notifies me if a commit has taken place. Based on some e-mail script from http://segfault.in/2010/12/sending-gmail-from-python/ and the argparse tutorial I managed to finish this script in just a few minutes. argparse is needed since Subversion calls the post-commit script with two parameters, the path to the repository and the version of the commit.

One note on the Google password: It is recommended to use application-specific passwords, see http://support.google.com/mail/bin/answer.py?hl=en&answer=1173270 for details.

#!/usr/bin/python
 
import smtplib # part of standard installation
import argparse # not part of standard installation
 
parser = argparse.ArgumentParser()
parser.add_argument("path", help="path to the repository on the server")
parser.add_argument("version", help="version of the commit")
 
args = parser.parse_args()
print args.path
print args.version
 
server = 'smtp.gmail.com'
port = 587
 
sender = '<sender mail address>'
recipient = '<receiver mail address>'
password = "<password>"
subject = 'SVN Commit'
body = 'SVN Commit: '
 
body = body +  args.path + ' ' +  args.version
 
headers = ["From: " + sender,
           "Subject: " + subject,
           "To: " + recipient,
           "MIME-Version: 1.0",
           "Content-Type: text/html"]
headers = "\r\n".join(headers)
 
session = smtplib.SMTP(server, port)
 
session.ehlo()
session.starttls()
session.ehlo
session.login(sender, password)
 
session.sendmail(sender, recipient, headers + "\r\n\r\n" + body)
session.quit()

Deutsche Zusammenfassung: Subversion stellt gewisse Einsprungspunkte bereit, zu denen man eigene Skripte ausführen kann. Mit Python lässt sich recht einfach ein Skript schreiben, das einen Nutzer über z.B. ein Commit informiert.

Uwe

Uwe Ziegenhagen likes LaTeX and Python, sometimes even combined. Do you like my content and would like to thank me for it? Consider making a small donation to my local fablab, the Dingfabrik Köln. Details on how to donate can be found here Spenden für die Dingfabrik.

More Posts - Website