Archive for the ‘Programmierung’ Category.
2022-03-19, 20:20
Vor kurzem hatte ich die Herausforderung, diverse XML Dateien zu kombinieren, die aufgrund einer Größenbeschränkung in einzelne, jeweils eigenständige, Dateien zerlegt worden waren. In jeder Datei fanden sich XML-Metaangaben in den ersten zwei und der letzten Zeile. Die Aufgabe bestand nun darin, den XML-Kopf und das XML-Ende nur einmal in der Ausgabedatei zu haben. An der folgenden Text-Datei kann man das gut erkennen:
Will ich nur einmal am Anfang
Will ich nur einmal am Anfang
Will ich
Will ich
Will ich
Will ich
Will ich
Will ich nur einmal am Ende
Mit Python ging es dann recht einfach, elegant und ausreichend performant (3 jeweils über 100 MB große Dateien ließen sich in ungefähr 12 Sekunden kombinieren):
- Die zu kombinierenden Dateien speichere ich in einem Array, hinzu kommt die Angabe des Ausgabepfads. Diese Information könnte man gegebenenfalls auch aus dem Dateisystem holen.
- Wir öffnen die Ausgabedatei zum Schreiben
- und nutzen dann ein enumerate, um den Zähler zu bekommen, bei welcher Datei wir gerade sind
- Bearbeiten wir die erste Datei, so brauchen wir alles bis auf die letzte Zeile
- Bearbeiten wir die letzte Datei, so brauchen wir nicht die ersten beiden Zeilen
- Bei den Dateien 2 bis n-1 brauchen wir weder die ersten zwei noch die letzte Zeile
files = ['f:/willich.txt', 'f:/willich.txt', 'f:/willich.txt']
output = 'F:/kombiniert.txt'
filecount = len(files)
print(f'Processing {filecount} files')
with open(output, 'w') as outputfile: # Ausgabe öffnen
for counter, file in enumerate(files):
print(counter, file)
with open(file, 'r') as fin:
data = fin.read().splitlines(True)
if counter == 0: # Erste Datei: alles bis auf die letzte Zeile
outputfile.writelines(data[:-1])
elif counter == filecount - 1: # letzte Datei, alles bis auf die ersten zwei Zeilen
outputfile.writelines(data[2:])
else: # die Dateien zwischen erster und letzter Datei, nicht die beiden ersten und die letzte Zeile
outputfile.writelines(data[2:-1]) |
files = ['f:/willich.txt', 'f:/willich.txt', 'f:/willich.txt']
output = 'F:/kombiniert.txt'
filecount = len(files)
print(f'Processing {filecount} files')
with open(output, 'w') as outputfile: # Ausgabe öffnen
for counter, file in enumerate(files):
print(counter, file)
with open(file, 'r') as fin:
data = fin.read().splitlines(True)
if counter == 0: # Erste Datei: alles bis auf die letzte Zeile
outputfile.writelines(data[:-1])
elif counter == filecount - 1: # letzte Datei, alles bis auf die ersten zwei Zeilen
outputfile.writelines(data[2:])
else: # die Dateien zwischen erster und letzter Datei, nicht die beiden ersten und die letzte Zeile
outputfile.writelines(data[2:-1])
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
2022-03-05, 22:24
Mit dem folgenden Schnipsel kann man den Pfad der Python.exe bestimmen, die das aktuelle Programm ausführt
import sys
print(sys.executable) |
import sys
print(sys.executable)
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
2021-12-23, 20:35
Hier ein kurzes Beispiel, wie man mit matplotlib Funktionen plotten kann.
import matplotlib.pyplot as plt
import numpy as np
ax = plt.gca()
plt.gca().set_aspect('equal')
ax.set_xticks(range(-6,6,1))
ax.set_yticks(range(-6,6,1))
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
x = np.linspace(-5,5,100)
y = 2*x+1
y2 = -0.5*x-2
plt.plot(x, y, 'r', label='2*x+1')
plt.plot(x, y2, 'g', label='-0.5*x-2')
plt.title('Linear Plots')
plt.legend(loc='upper left')
plt.grid()
plt.show() |
import matplotlib.pyplot as plt
import numpy as np
ax = plt.gca()
plt.gca().set_aspect('equal')
ax.set_xticks(range(-6,6,1))
ax.set_yticks(range(-6,6,1))
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
x = np.linspace(-5,5,100)
y = 2*x+1
y2 = -0.5*x-2
plt.plot(x, y, 'r', label='2*x+1')
plt.plot(x, y2, 'g', label='-0.5*x-2')
plt.title('Linear Plots')
plt.legend(loc='upper left')
plt.grid()
plt.show()

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
2021-12-23, 20:14
Angenommen, wir haben eine Excel-Datei Daten.xlsx
mit Werten, die in ein entsprechendes XML-Dokument überführt werden müssen.

Mit Python und der Jinja2 Template-Engine ist das flink gemacht. Zuerst definieren wir das Template template.xml
:
<?xml version='1.0' encoding='UTF-8'?>
<table name="Tablename">
{% for _,row in data.iterrows() %}
<ROW>
<COLUMN1>{{row['column1']}}</COLUMN1>
<COLUMN2>{{row['column2']}}</COLUMN2>
<COLUMN3>{{row['column3']}}</COLUMN3>
</ROW>
{% endfor %}
</table> |
<?xml version='1.0' encoding='UTF-8'?>
<table name="Tablename">
{% for _,row in data.iterrows() %}
<ROW>
<COLUMN1>{{row['column1']}}</COLUMN1>
<COLUMN2>{{row['column2']}}</COLUMN2>
<COLUMN3>{{row['column3']}}</COLUMN3>
</ROW>
{% endfor %}
</table>
Dann definieren wir den Python-Code:
import pandas as pd # data wrangling
import jinja2 # template engine
import os # for file-related stuff
# create jinja env that can load template from filesystem
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(os.path.abspath('.')))
df = pd.read_excel('Daten.xlsx')
template = jinja_env.get_template('template.xml')
with open('FertigesXML.xml','w') as output:
output.write(template.render(data=df)) |
import pandas as pd # data wrangling
import jinja2 # template engine
import os # for file-related stuff
# create jinja env that can load template from filesystem
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(os.path.abspath('.')))
df = pd.read_excel('Daten.xlsx')
template = jinja_env.get_template('template.xml')
with open('FertigesXML.xml','w') as output:
output.write(template.render(data=df))
Lassen wir den Python-Code laufen, so erhalten wir das folgende XML:

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
2021-09-25, 10:51
A while ago (https://www.uweziegenhagen.de/?p=2373) I had an article on how to read the ECB fx rates file with Python. Some time has passed, there are other options in Python 3.
Option 1: Make the Python 2 code run with Python 3
import xml.etree.ElementTree as ET
import urllib.request
root = ET.parse(urllib.request.urlopen('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')).getroot()
for child in root[2][0]:
curr = child.get('currency')
rate = child.get('rate')
print(curr, rate) |
import xml.etree.ElementTree as ET
import urllib.request
root = ET.parse(urllib.request.urlopen('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')).getroot()
for child in root[2][0]:
curr = child.get('currency')
rate = child.get('rate')
print(curr, rate)
Option 2: Use pandas >=1.3
Starting with version 1.3 pandas offers the read_xml
command, so upgrade using
pip3 install --upgrade pandas
or conda update pandas
.
from urllib.request import urlopen
import pandas as pd
df = pd.read_xml(urlopen('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'),xpath='//*[@currency]')
print(df) |
from urllib.request import urlopen
import pandas as pd
df = pd.read_xml(urlopen('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'),xpath='//*[@currency]')
print(df)
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
2021-05-09, 11:03
Hier ein bisschen Python-Code, um zwei CSV Dateien miteinander zu vergleichen. Die Ergebnisse des spalten- und zeilenweisen Vergleichs werden dann zusammengefasst dargestellt, um schnell einen Überblick zu bekommen, wo eine tiefergehende Analyse notwendig ist.
import sys
import collections
import pandas as pd
from tabulate import tabulate
file1 = pd.read_csv('file1.csv', sep=';', encoding='UTF-8')
file2 = pd.read_csv('file2.csv', sep=';', encoding='UTF-8')
columnnames1 = list(file1)
columnnames2 = list(file2)
if collections.Counter(columnnames1) == collections.Counter(columnnames2):
print ("Number of columns and Names match, Comparison possible...\n\n")
else:
print ("Number of columns and Names are not matching!!! Please check the input!")
sys.exit('Error!')
# add suffixes to distinguish between actual and expected in the merger
file1 = file1.add_suffix('_e') # expected
file2 = file2.add_suffix('_t') # t
# merge them using the given key, use outer join
comparison = pd.merge(file1,file2, how='outer',
left_on=['Key_e'],
right_on=['Key_t'])
# create the columnwise comparison
for col in columnnames1:
comparison[(col + '_c')] = comparison[(col + '_t')] == comparison[(col + '_e')]
# reorder the columns
comparison=comparison.reindex(sorted(comparison.columns),axis=1)
print(tabulate(comparison, tablefmt="pipe", headers="keys"))
# save the result as Excel file
comparison.to_excel('result.xlsx')
# names of the comparison column
check_colnames= [s + '_c' for s in columnnames1]
# initialize an empty dataframe for the log
logdf=pd.DataFrame(index=[True,False])
for column in check_colnames:
t=comparison[column].value_counts() # returns a series
tt=pd.DataFrame(t) # makes a DF out of the series
logdf = logdf.join(tt,how='outer') # join the two dfs
# transpose for better readability
logdf = logdf.transpose()
# Ensure fixed sequence of the columns
logdf=logdf.reindex(sorted(logdf.columns),axis=1)
# write to disk
logdf.to_excel('logfile.xlsx')
# for better viewing on the screen
logdf.fillna('-',inplace=True)
pd.options.display.float_format = '{:,.0f}'.format
print(tabulate(logdf, tablefmt="pipe", headers="keys")) |
import sys
import collections
import pandas as pd
from tabulate import tabulate
file1 = pd.read_csv('file1.csv', sep=';', encoding='UTF-8')
file2 = pd.read_csv('file2.csv', sep=';', encoding='UTF-8')
columnnames1 = list(file1)
columnnames2 = list(file2)
if collections.Counter(columnnames1) == collections.Counter(columnnames2):
print ("Number of columns and Names match, Comparison possible...\n\n")
else:
print ("Number of columns and Names are not matching!!! Please check the input!")
sys.exit('Error!')
# add suffixes to distinguish between actual and expected in the merger
file1 = file1.add_suffix('_e') # expected
file2 = file2.add_suffix('_t') # t
# merge them using the given key, use outer join
comparison = pd.merge(file1,file2, how='outer',
left_on=['Key_e'],
right_on=['Key_t'])
# create the columnwise comparison
for col in columnnames1:
comparison[(col + '_c')] = comparison[(col + '_t')] == comparison[(col + '_e')]
# reorder the columns
comparison=comparison.reindex(sorted(comparison.columns),axis=1)
print(tabulate(comparison, tablefmt="pipe", headers="keys"))
# save the result as Excel file
comparison.to_excel('result.xlsx')
# names of the comparison column
check_colnames= [s + '_c' for s in columnnames1]
# initialize an empty dataframe for the log
logdf=pd.DataFrame(index=[True,False])
for column in check_colnames:
t=comparison[column].value_counts() # returns a series
tt=pd.DataFrame(t) # makes a DF out of the series
logdf = logdf.join(tt,how='outer') # join the two dfs
# transpose for better readability
logdf = logdf.transpose()
# Ensure fixed sequence of the columns
logdf=logdf.reindex(sorted(logdf.columns),axis=1)
# write to disk
logdf.to_excel('logfile.xlsx')
# for better viewing on the screen
logdf.fillna('-',inplace=True)
pd.options.display.float_format = '{:,.0f}'.format
print(tabulate(logdf, tablefmt="pipe", headers="keys"))
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
2021-05-08, 09:54
Sharepoint-Server haben ein Maximum von 256 Zeichen für Pfadangaben, Leerzeichen in Datei- und Ordnernamen werden dabei als „%20“ dargestellt, sodass für jedes Leerzeichen drei Zeichen „draufgehen“. Mit dem folgenden Powershell-Skript kann man die Dateien in einem Verzeichnis identifizieren, die das Limit vermutlich sprengen.
Die erzeugte CSV-Datei hat drei Spalten: Pfadlänge, Pfadlänge wenn Leerzeichen als „%20“ dargestellt werden, Pfad.
gci "K:\inputpath" | Select @{N="Path Length";E={$_.FullName.Length}}, @{N="URL Length";E={$_.FullName.replace(' ','+++').Length}},
Fullname | Export-Csv -NoTypeInformation -Delimiter ";" -Path "t:\ABC\filelaengen.csv" |
gci "K:\inputpath" | Select @{N="Path Length";E={$_.FullName.Length}}, @{N="URL Length";E={$_.FullName.replace(' ','+++').Length}},
Fullname | Export-Csv -NoTypeInformation -Delimiter ";" -Path "t:\ABC\filelaengen.csv"
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
2021-05-02, 21:12
Vor ein paar Wochen hat jemand in einer Facebook-Gruppe gefragt, wie man — abhängig von einer Soll/Haben-Spalte — in Excel einen Wert mit positivem oder negativem Vorzeichen darstellen kann. Die Lösung ist ganz einfach, wenn man die WENN()
Funktion kennt.

Spannender ist die Frage: Geht es auch ohne Wenn()
und ohne VBA? Die Antwort ist ja, von hinten durch die Brust ins Auge…
Mittels CODE()
Funktion ermitteln wir den ASCII Code des Buchstabens, bei „S“ ist das 83, bei „H“ 72.

Als nächstes ziehen wir von diesem Wert 84 ab und vergleichen den Wert mit -1. Excel wertet dies für „S“ als WAHR aus, für „H“ als FALSCH. Da man mit WAHR (=1) und FALSCH (=0) prima in Excel weiterrechnen kann, multiplizieren wir den Wert mit -2 und addieren 1.
Für „S“ ergibt sich 1 (für „WAHR“) * -2 = -2 + 1 = 1, für „H“ ergibt sich 0 (für „FALSCH“) * -2 = 0 + 1 = 1. Damit muss man dann nur noch den ursprünglichen Betrag multiplizieren…


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
2021-02-24, 21:49
Die Uhr rechts unten in der Windows-Taskleiste kann man auch so einstellen, dass die Sekunden angezeigt werden
Dazu mit regedit den Schlüssel \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced –> ShowSecondInSystemClock auf 1 setzen.
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
2021-02-14, 13:09
Hier ein einfaches Beispiel, wie man mit Python und LaTeX ein PDF mit Kursinformationen erstellen kann.
Zuerst der Python-Teil, der die Apple-Kursdaten seit dem 1.1.2021 in einen Dataframe lädt und dann in eine LaTeX-Tabelle schreibt:
import pandas
import pandas_datareader.data as web
YAHOO_TODAY="http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=sd1ohgl1vl1"
history = web.DataReader('AAPL', "yahoo", start="2021-1-1")
history.to_latex('aapl.tex') |
import pandas
import pandas_datareader.data as web
YAHOO_TODAY="http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=sd1ohgl1vl1"
history = web.DataReader('AAPL', "yahoo", start="2021-1-1")
history.to_latex('aapl.tex')
Dann noch der LaTeX-Teil, der a) den Python-Code aus dem LaTeX-Lauf heraus ausführt und b) die erzeugte Tabellen-Datei nur dann einbindet, wenn sie wirklich auch erzeugt wurde.
\documentclass[12pt,ngerman]{scrartcl}
\usepackage[a4paper, top=1cm,bottom=1cm,left=1cm, right=1cm]{geometry}
\usepackage[T1]{fontenc}
\usepackage{booktabs}
\makeatletter
\newcommand{\testfileexists}[1]{%
\IfFileExists{#1}%
{\def\inputtestedfile{\@@input #1 }}
{\let\inputtestedfile\@empty}%
}
\makeatother
\begin{document}
\write18{python runpy.py}
\testfileexists{aapl}
\inputtestedfile
\end{document} |
\documentclass[12pt,ngerman]{scrartcl}
\usepackage[a4paper, top=1cm,bottom=1cm,left=1cm, right=1cm]{geometry}
\usepackage[T1]{fontenc}
\usepackage{booktabs}
\makeatletter
\newcommand{\testfileexists}[1]{%
\IfFileExists{#1}%
{\def\inputtestedfile{\@@input #1 }}
{\let\inputtestedfile\@empty}%
}
\makeatother
\begin{document}
\write18{python runpy.py}
\testfileexists{aapl}
\inputtestedfile
\end{document}
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