Fortran und Python

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
xaggi
User
Beiträge: 5
Registriert: Montag 17. Mai 2010, 16:36

Montag 17. Mai 2010, 16:41

Hallo,

ich würde gerne ein Fortran-Programm in Python verwenden. Allerdings sollte dieses auf beliebigen Platformen (jedenfalls den üblichen) laufen, sofern dort Python mit NumPy/SciPy installiert ist.

Verstehe ich das richtig, dass ein mit f2py kompiliertes Modul *nicht* Plattformunabhängig ist?
Gibt es Tools um den Fortran-Code nicht zu wrappen sondern tatsächlich in Plattformunabhängigen Python-Code zu übersetzen, oder muss ich da mit Handarbeit ran?

Grüße
BlackJack

Montag 17. Mai 2010, 16:52

@xaggi: Das wird nicht gehen. Man verwendet Fortran ja in der Regel damit das möglichst effizient auf der Zielplattform läuft, also in Maschinensprache für den Zielrechner übersetzt wird. Damit ist die Plattformunabhängigkeit im Grunde dahin. Nach Python beziehungsweise Bytecode für den Python-Interpretierer willst Du Fortran ganz bestimmt nicht übersetzen.
xaggi
User
Beiträge: 5
Registriert: Montag 17. Mai 2010, 16:36

Montag 17. Mai 2010, 17:19

Okay, das heißt ich werde das Programm nach Vorlage des Fortran-Codes komplett neu schreiben müssen?
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Sonntag 23. Mai 2010, 15:36

Nicht kpl. neu schreiben, sondern vmtl. nur neu kompilieren.
BlackJack

Sonntag 23. Mai 2010, 16:25

@HerrHagen: Das Ziel ist ja gerade *nicht* für jede Plattform neu kompilieren zu müssen, sondern mit fertig installierbaren Paketen wie `numpy` auszukommen. So habe ich das jedenfalls verstanden, dass der OP ein Programm schreiben möchte, das für die Installation auf beliebigen Systemen auf denen Python und `numpy` bereits installiert sind, kein Fortran-Compiler nötig ist.
xaggi
User
Beiträge: 5
Registriert: Montag 17. Mai 2010, 16:36

Sonntag 23. Mai 2010, 16:31

Ja, genau so war es gemeint, danke.
Ich hab es inzwischen übrigens zum größten Teil in Python-Code übersetzt, so dass sich meine Frage gewissermaßen erledigt hat.
BerndB
User
Beiträge: 14
Registriert: Freitag 28. Mai 2010, 15:49

Donnerstag 3. Juni 2010, 15:47

Moin zusammen,

bin auf der Suche nach Python-Schnittstellen (inbesondere Fortran) hier hängen geblieben.
Hatte mir auch schon mal f2py heruntergeladen, aber noch nicht weiter damit gespielt.
Mich reizt hierbei vorallem die Geschwindigkeit von Fortran mit der unkompllizierteren I/O von Python
zu verbinden.
Hat hier schon mal jemand experimentiert und kann mir eine paar Zeilen Code - Daten von Python an
Fortran und wieder zurück zur Verfügung stellen oder geht das ganze nur in eine Richtung f2py = Fortran2Python ?

Grüße
Bernd
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Donnerstag 3. Juni 2010, 18:23

Hallo,

ich kann dir nur ein paar Zeilen Fortran die ich mal für f2py geschrieben hatte zeigen. Das waren ein paar Bildverarbeitungsoperationen.
Man gibt ein numpy array rein und bekommt eins raus:
http://pastebin.com/siFXWVHH
Ich hoffe das diese Version so lauffähig ist. Kanns nicht mehr genau sagen, da es schon ne Weile her ist und es dann doch anders realisiert wurde (als C-Extension, die Fortran-Version war zwar schneller und schöner, aber es sollten keine 3 Sprachen verwendet werden).

MFG HerrHagen
BerndB
User
Beiträge: 14
Registriert: Freitag 28. Mai 2010, 15:49

Montag 7. Juni 2010, 07:20

Moin HerrHagen,

wenn ich die Fortran-Zeilen richtig verstehe, lege ich einfach mit einem Kommentar !f2py einen
Verbindung für den Datentransfer zwischen Python und Fortran. Wie läuft denn jetzt aber die Übersetzung genauer. Ich habe z.B. mein Hauptprogramm in Python und rufe die Subroutinen
aus dem Fortran-Code auf und bekomme ein Ergebnis zurück. Jetzt muß doch eine Übersetzung meiner
Python-Daten nach Fortran und wieder zurück erfolgen. Macht das allein der Kommentar !f2py mit der
Funktion intent() und dem Schlüsselwort in / out? Hängt sich das f2py-Modul als Übersetzter einfach dazwischen? Oder muß ich die Funktion intent() erst mit leben füllen? Habe bisher nur einen kurzen Blick in die Dokumentation von f2py werfen können, werde aber nach intent() und eventuellen Beispielen suchen.

Trotzdem vielen Dank für
die Code-Zeilen
bis bald
Bernd
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Montag 7. Juni 2010, 18:33

Das wars wirklich schon. Intent ist ein vordefiniertes Schlüsselwort von f2py. Es bestimmt welche Daten aus der Funktion rein (in) und raus (out) gehen. Zum kompilieren genügt bei installiertem Fortran Compiler ein einfacher Aufruf:

Code: Alles auswählen

python C:\Python25\scripts\f2py.py -c --fcompiler=gnu95 --compiler=mingw32 -m filters c:\python25\filters.f95
Das ganze steht dann wie eine normale C-Extension zur Verfügung. D.h. du kannst das Kompilat ohne Umwege verwenden. In dem Fall z.B. so:

Code: Alles auswählen

import filters
import numpy
a = numpy.random.randint(0, 9, (6, 9))
print a
b = filters.dilation(a)
print b

Code: Alles auswählen

[[3 1 4 1 5 6 6 4 4]
 [1 3 8 1 3 4 4 0 0]
 [7 3 5 7 0 2 4 5 1]
 [1 0 0 2 4 7 0 0 7]
 [0 2 5 8 2 4 2 1 8]
 [2 6 5 8 7 8 4 1 4]]

[[3 1 4 1 5 6 6 4 4]
 [1 8 8 8 7 6 6 6 0]
 [7 8 8 8 7 7 7 7 1]
 [1 7 8 8 8 7 7 8 7]
 [0 6 8 8 8 8 8 8 8]
 [2 6 5 8 7 8 4 1 4]]
BerndB
User
Beiträge: 14
Registriert: Freitag 28. Mai 2010, 15:49

Freitag 11. Juni 2010, 07:34

Moin HerrHagen,
moin allen anderen Lesern/Helfern/Wissenden

vielen Dank für den Ablaufplan zum Einbinden von Fortran-Datein in Python.
Habe es soweit geschaft, dass mir f2py keinen Fehler ausgibt error = none und eine namemodul.c Datei entsteht.
(Kann der Namensanhang modul unterdrückt werden?)

Nur das Importieren funktioniert nicht, da er das Modul nicht findet. Fehlt hier nur eine Aktualisierung des
Suchpfades sys.path, PATH oder PYTHONPATH ? (Worin liegt eingentlich der Unterschied zwischen PATH(global?) und PYTHONPATH (lokal, nur für Python?)?) Ist es nicht zweckmäßig für die eigenen Module einen Import-Ordner anzulegen, der
dann unter Python mit import abgefragt werden kann? Wieviele Ebene werden von dem angebenen Ordner im sys.path eigentlich durchsucht - nur eine ?

Mein Kommando sah übrigens so aus
python C:\Python25\scripts\f2py.py -c --fcompiler=g95 -m C:\Ausgabe_F2PY\filters c:\python25\filters.f95

Wird durch f2py wirklich kompilierter Fortran-Code verwendet oder der Code nur nach C übersetzt und in C-kompiliert und
dann (wenn der Import funktioniert) in Python verwendet?

bis bald und ein schönes Wochenende
Bernd
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Sonntag 13. Juni 2010, 12:25

Wird durch f2py wirklich kompilierter Fortran-Code verwendet oder der Code nur nach C übersetzt und in C-kompiliert und
dann (wenn der Import funktioniert) in Python verwendet?
Es wird wirklich Fortran-Code verwendet. C wird nur für das Interface zwischen Fortran und Python gebraucht.
Nur das Importieren funktioniert nicht, da er das Modul nicht findet. Fehlt hier nur eine Aktualisierung des
Suchpfades sys.path, PATH oder PYTHONPATH ? (Worin liegt eingentlich der Unterschied zwischen PATH(global?) und PYTHONPATH (lokal, nur für Python?)?) Ist es nicht zweckmäßig für die eigenen Module einen Import-Ordner anzulegen, der
dann unter Python mit import abgefragt werden kann? Wieviele Ebene werden von dem angebenen Ordner im sys.path eigentlich durchsucht - nur eine ?
Versteh ich nicht. Was willst du mit sys.path? Wird denn kein .pyd erzeugt? Die kannst du doch einfach importieren wenn sie im selben Verzeichnis wie die ausführende py-Datei liegt.
Oder meinst du das das kompilieren nicht funktioniert weil er den Compiler nicht findet? Dann müssten einige Umgebungsvariablen manuell gesetzt werden. Ich habe gerade meine Aufzeichnungen von damals entdeckt in denen ich mir notierte was gesetzt wurde bzw. werden musste:

Code: Alles auswählen

MinGW32------------------------------------------------

http://www.mingw.org/download.shtml
Umgebungsvariablen für MinGW:
MINGW_PATH -> C:\MinGW
MINGW_LIBS -> C:\MinGW\lib;C:\MinGW\lib\gcc\mingw32\3.4.5
PATH -> %MINGW_PATH%\bin

GFortran ----------------------------------------------

http://gcc.gnu.org/wiki/GFortranBinaries
Umgebungsvariablen für GFortran95:
C_INCLUDE_PATH -> C:\Programme\gfortran\include
PATH -> C:\Programme\gfortran\bin
Im Verzeichnis im dem f2py installiert wurde (z.B. C:\Python25\Lib\site-packages\numpy\f2py) gibt es auch ein Skript names diagnose.py mit dem gezeigt wird welche Compiler erkannt wurden. Das solltest du vielleicht mal laufen lassen.
Habe es soweit geschaft, dass mir f2py keinen Fehler ausgibt error = none und eine namemodul.c Datei entsteht.
(Kann der Namensanhang modul unterdrückt werden?)
Die Datei ist ja nur ein Zwischenschritt. Als Modul kommt was raus was den Namen hat den du in der Kommandozeile angegeben hast.
BerndB
User
Beiträge: 14
Registriert: Freitag 28. Mai 2010, 15:49

Montag 14. Juni 2010, 10:16

Moin HerrHagen,

eine *.pyd Datei habe ich nicht gesehen, aber auch nicht da nach gesucht, vielleicht wurde sie ja woanders abgelegt.
Werde mich auch noch mit den Umgebungsvariablen beschäftigen, insbesonder mit dem C-Kompiler und auch mit der Antwort der diagnose.py.

Vielen Dank bis jetzt schon mal
und bis bald

Bernd

P.S.: Habe mir nochmal die Ausgabe beim Durchlauf von f2py angesehen und dort wird anggeben, dass kein numeric.py und numarry.py gefunden wurde. Ich dachte das wäre mittlererweile in NumPy enthalten. Liegt es vielleicht daran, dass keine *.pyd Datei entsteht?
BerndB
User
Beiträge: 14
Registriert: Freitag 28. Mai 2010, 15:49

Dienstag 10. August 2010, 10:38

Moin zusammen,

nachdem ich das MSVisualStudio aufgespielt habe läuft auch der Transfer von Fortran an Python mit
der *.pyd Datei.

Jetzt habe ich allerdings folgendes Problem mit einem 'nicht auflösbaren Zeichen' in meinem Fortran-Code, wobei der Fortran-Compiler keinen Fehler auswirft. Ich möchte ein Feld übergeben, verarbeiten und das Ergebnis (ein kleiners Feld) wieder übergeben. Die Feldlänge übergebe ich auch und sie wird bei der Verarbeitung mit f2py als optionale Variable erkannt (ich vermute das die Feldlänge auch aus dem Feld selbst bestimmt wird). Jetzt möchte ich einen Zwischenspeicher der selben Länge anlegen und bekomme dann bei einem Zugriff den Link-Fehler.

SUBROUTINE(eingang, laenge, ergebnis)

INTEGER, INTENT(IN) :: laenge
REAL, DIMENSION(laenge), INTENT(IN) :: eingang
REAL, DIMENSION(laenge/2), INTENT(OUT) :: ergebnis

INTEGER, DIMENSION(laenge) :: speicher

speicher(1) = 1

Sobald ich die letzte Fortran-Zeile verwende bekomme ich den Link-Fehler. Worin liegt mein Fehler ?

Bis bald
Bernd

P.S.:
Wenn ich die Variable speicher als INTENT(INOUT) definiere läuft f2py durch. Doch eigentlich
möchte ich die interne Varaibale nicht als Ein- und Rückgabewert, sondern eben nur als
Zwischenspeicher verwenden.

Jetzt hab ich bei einer anderen Funktion mit dem Potenzieren ** Schwierigkeiten.
2**3 funktioniert, auch 2**3.0, bei 2**3.5 steigt f2py wieder aus. Was ist hier los?
Antworten