Cython als Compiler benutzen um Python3 zu C konvertieren

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
010010
User
Beiträge: 14
Registriert: Freitag 3. Juni 2016, 20:33

Donnerstag 3. Januar 2019, 06:36

Guten Tag. Habe angefangen meine Python Scripte zu konvertieren mit Cython. Doch immer wenn ich das versuche kann ich es nicht von einer Data.c zu einer anwendbaren Datei machen. Sprich zu einem starter oder einfach nur Terminal Programm.

Es kommt immer die gleiche Nachricht. Wenn ich es compilieren will mit: gcc -Os /usr/include/python3.7m -o ParabelPunkte ParabelPunkte.c -lpython3.7m -lpthread -lm -lutil -ldl

Wie es in der Anleitung steht. Kommt die Nachricht:
ParabelPunkte.c:4:10: schwerwiegender Fehler: Python.h: Datei oder Verzeichnis nicht gefunden
#include "Python.h"
^~~~~~~~~~
Kompilierung beendet.

Habe meine Ordner überprüft. Es ist Python3.7m wo alles drin sein sollte. Nur halt der Fehler. Hoffe jemand kann mir kurz und knapp erklären was mir fehlt wenn Das Python.h nicht drin ist?
Und ja es steht das es nicht drin ist. Doch meine Packetverwaltung findet nichts für Python.h. Sprich einfache schnelle lösung für mich gerade.
010010
User
Beiträge: 14
Registriert: Freitag 3. Juni 2016, 20:33

Donnerstag 3. Januar 2019, 06:55

So habe meinen Fehler gefunden. Mir fehlte das -I. Also simpler fehler. Doch das Layout ist nicht so wie es sein sollte. Für Print("Bla", a, "Was auch immer.")
Macht der sowas wie ('Bla' die passende Nummer ' ' Was auch immer. ') Sowas in der Art. Also muss ich jetzt alles in ein eigenes print packen separat damit er mein Design richtig umsetzt? Das passiert übrigenst nur wenn ich Dinge mit Komma trenne. :/
Sirius3
User
Beiträge: 9393
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 3. Januar 2019, 08:44

@010010: „sowas in der Art” hilft nicht wirklich bei der Fehlersuche, da mußt Du schon exakt sein. Was hast Du genau gemacht, welchen Code? Was ist die genaue Ausgabe?
010010
User
Beiträge: 14
Registriert: Freitag 3. Juni 2016, 20:33

Donnerstag 3. Januar 2019, 09:26

Ich habe es jetzt mit mehr als einer Software versucht. Meine tkinter Fenster laufen. Musste nur in meinen Musik Sachen bestimmte Zeiten umstellen. Da der Ton sonst 5min läuft und nicht nur 0,3s.

So jetzt aber zu meinem Problem. Beim Convertieren meiner Software für Parabeln habe ich ein Layout. Nichts besonderes da es nur im Terminal läuft. Unter Python sieht es so aus:

Parbabel berechnen ( y=ax²+bx+c ) aller Werte.

a = 9
b = 12
c = -2

Ergebnisse der Parabel:

Scheitelpunkt: y = 9 * (x + 0.6666666666666666 )² -6.0
y = -2
x1 = -1.4831632475943928
x2 = 0.1498299142610594



Doch nachdem ich es durch cython und dann mit gcc Compiliert habe sieht es so aus:

Parbabel berechnen ( y=ax²+bx+c ) aller Werte.

a = 9
b = 12
c = -2

Ergebnisse der Parabel:
('\nScheitelpunkt: y =', 9, '* (x +', 0.6666666666666666, ')² ', -6.0)
('y = ', -2)
('x1 = ', -1.4831632475943928)
('x2 = ', 0.1498299142610594, '\n')

Man kann schnell sehen das er bei dem print() Befehl nur Variablem wie \n oder das , zum abtrennen des Strings vom Nummerischen Wert. Die Ganzen Zeichen mit nimmt.

Hier noch der Code:

## Berechnung von Schnittpunkten einer Parabel

import math

print("\nParbabel berechnen ( y=ax²+bx+c ) aller Werte.")

while True:
a = eval(input("\na = "))
b = eval(input("b = "))
c = eval(input("c = "))

b2 = b / a
c2 = c / a

b3 = b2 / 2

xn = c2 - (b3**2)

xs = a * xn

xe = -1 * xn

print("\nErgebnisse der Parabel:")

if (b3 < 0):
if (xs >= 0):
print("\nScheitelpunkt: y =", a, "* (x", b3, ")² +", xs)
if (xs < 0):
print("\nScheitelpunkt: y =", a, "* (x", b3, ")² ", xs)

if (b3 >= 0):
if (xs >= 0):
print("\nScheitelpunkt: y =", a, "* (x +", b3, ")² +", xs)
if (xs < 0):
print("\nScheitelpunkt: y =", a, "* (x +", b3, ")² ", xs)

print("y = ", c)

if (xe > 0):
xp1 = -math.sqrt(xe)
xp2 = math.sqrt(xe)
print("x1 = ", xp1 - b3)
print("x2 = ", xp2 - b3, "\n")

if (xe < 0):
print("\nEs gibt keine Nullstellen!\n")
Benutzeravatar
__blackjack__
User
Beiträge: 2552
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 3. Januar 2019, 10:12

@010010: In der Cython-Dokumentation steht das bauen per `setup.py` und per ``cythonize`` an den ersten beiden Stellen. Was ist bei Dir so besonders, dass Du das so kompliziert manuell machen willst? Und warum das 'm' in ``python3.7m``? Das sollte nicht nötig sein, macht aber andererseits Probleme wenn es auf einem System verwendet wird, wo das Python das normale `malloc()` für Python-Objekte verwendet. Und wenn Du es schon manuell unter Python machst, warum dann alle Optionen für Compiler und Linker selber angeben, mit der Gefahr sich zu vertippen, oder etwas zu vergessen? Ich würde ja mindestens ``python3-config`` dafür benutzen, wenn ich den C-Compiler manuell aufrufen würde.

Bezüglich des ”Layouts”: So sieht das aus wenn man Dein Python 3-Programm mit Python 2 ausführt, weil ``print`` da eine Anweisung und keine Funktion ist, und ``print(a, b)`` da nicht bedeutet „rufe `print()` mit den Argumenten `a` und `b` auf“, sondern „führe ``print`` aus um das Tupel ``(a, b)`` auszugeben“. Du möchtest vielleicht ``cython`` sagen, dass es sich um Python 3-Code handelt. Eventuell hilft auch eine entsprechende „she-bang“-Zeile schon.

Zusätzlich könntest Du Dir mal `format()` anschauen, und wie man Zahlen mit Vorzeichen formatiert. Damit kannst Du Dir eine Menge von den ``if``\s mit den fast gleichen Inhalten sparen.
“All tribal myths are true, for a given value of 'true'.” – Terry Pratchett, The Last Continent
Sirius3
User
Beiträge: 9393
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 3. Januar 2019, 10:15

Du hast vergessen bei Cython die Pythonversion anzugeben, was auch die Warnung gesagt hat, die Du ignoriert hast.

Zum Code: benutze kein eval, wenn Du nur einfache float umwandeln willst. Die vielen b1,b3,b3 sind verwirrend, benutze sprechende Variablennamen. Die Klammern um die if-Bedingungen sind allesamt überflüssig, in Python schreibt man keine Klammern bei if. Statt print mit Komma wäre Stringformatierung lesbarer. Für sqrt einfach xe ** 0.5 schreiben, dann spart man sich den math-Import. Wenn man eine Bedingung im if hat und gleich danach die gegenteilige Bedingung, nimmt man else. Die vierfach wiederholte print-Anweisung ist sowieso unglaublich kompliziert, wenn man einfache String-Formatierung benutzen würde. Der Fall einer Nullstelle ist nicht abgebildet.

Code: Alles auswählen

print("\nParbabel berechnen ( y=ax²+bx+c ) aller Werte.")
while True:
	a = float(input("\na = "))
	b = float(input("b = "))
	c = float(input("c = "))

	b /= (2*a)
	xn = c / a - b ** 2

	print("\nErgebnisse der Parabel:")
	print("\nScheitelpunkt: y = {:f} * (x {:+f})² {:+f}".format(a,b, a*xn))
	print("y = {}".format(c))

	if xn < 0:
		xe = (-xn) ** 0.5
		print("x1 = {}".format(-xe - b))
		print("x2 = {}\n".format(xe - b))
    elif xn == 0:
		print("x = {}".format(-b))
    else:
		print("\nEs gibt keine Nullstellen!\n")
010010
User
Beiträge: 14
Registriert: Freitag 3. Juni 2016, 20:33

Donnerstag 3. Januar 2019, 11:17

Die Pakete sagen eindeutig das es mindestens 3.2 Version von Python benutzt wird. Also sollte es ja alufen wenn es um print geht.
mit dem float habe ich schon andere tkinter Sachen gemacht. Dort kommt halt noch Variable.get() dazu.
Der grund warum es so kompliziert ist. Der debugger gab mir immer fehler aus. Also hab ich es immer weiter aufgespalten. Damit ich jeden einzelnen Fehler sehen konnte in einer Zeile. Sprich wie auf dem Blatt Papier schritt für Schritt.

Nochmal zurück zu meinem design. Also wählt der Python2 Code an eher. Gibt es einen Befehl das auch ordentlich zu machen mit dem Compiler? Ich mag es so wie ich das gemacht hab. Eine eigene compiler Datei anlegen wollte ich eher vermeiden.


Danke für dir hilfe mal wieder. Man denkt doch nicht mehr an alles.
__deets__
User
Beiträge: 4836
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 3. Januar 2019, 11:22

Wieso willst du sowas vermeiden? Die Probleme, die du hast, kommen mit hoher Wahrscheinlichkeit genau da her, dass du die ausgetretenen Pfade verlaesst. Das sollte man halt nur tun, wenn man weiss, was man tut. Und selbst dann ist es fragwuerdig, denn einen Gewinn kann man dadurch nicht erkennen.

Du hast bis dato immer noch verschwiegen, wie du den Code generierst. Einfach nur "durch cython gejagt" kann ja alles moegliche bedeuten, Fehler inklusive. Wenn ich mir die Kommandozeilen-Argumente von "cython3" anschaue, habe ich da auch schon konkrete Verdachtsmomente...
Benutzeravatar
__blackjack__
User
Beiträge: 2552
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 3. Januar 2019, 11:37

@010010: Welche Pakete sagen was? Woher weiss Deiner Meinung nach ``cython`` das es sich um Python 3 handelt und nicht um Python 2?

Was ist „eine eigene compiler Datei“? Hast Du Dir ``cythonize`` in der Dokumentation denn mal angeschaut? Da muss man nichts extra anlegen. Einfach mit den passenden Argumenten aufrufen.
“All tribal myths are true, for a given value of 'true'.” – Terry Pratchett, The Last Continent
010010
User
Beiträge: 14
Registriert: Freitag 3. Juni 2016, 20:33

Donnerstag 3. Januar 2019, 11:56

Ich habe vor ein paar tagen das mal Probiert. Da wollte es nicht. Heute morgen hatte ich wieder lust dazu. Habe gerade erst angefangen und lese mir gerade mehr Ausgabe möglichkeiten durch. Ich habe mich beim convert auf eine Anzeige auf einer Cython Seite bezogen. Eher eine die Das Thema behandelt es von Python3 zu C umwandeln zu können. Hab auch alles mögliche schon umgewandelt. Die tkinter sachen liefen super. Bei meinen Tönen die ich generiert habe über eine Schaltfläche musste ich die Duration ändern. Da ich die unnötogerweise als 200/1000 drinne stehen hatte. Mir 0.2 war es viel besser und C hat daraus nicht 3min gemacht. Nur die beiden Sachen die im terminal ausgegeben werden haben durch den print befehl eine falsche ausgabe. Halt durchgehen String mit den Variablen die eine Zahl bekommen. Da versuche ich jetzt zu lernen was man besser machen kann. Damit das in Zukubnft schneller geht.

Meine Daten für die Convert Sachen sind alle aus meinem Ordner python3.7m die genau dafür sind. Würde ich in dem Kommando 2.7.xm rein schreiben wäre es anders. Nur habe ich keine anderen Python Ordner dafür.
__deets__
User
Beiträge: 4836
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 3. Januar 2019, 11:58

🤷‍♂️
Sirius3
User
Beiträge: 9393
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 3. Januar 2019, 12:05

200/1000 ist halt in Python2 0 und nicht 0.2. Das hat nichts mit C zu tun, sondern nur daran, das Du cython falsch benutzt.
Benutzeravatar
__blackjack__
User
Beiträge: 2552
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 3. Januar 2019, 12:17

@010010: Es ist manchmal ein bisschen schwer dem zu Folgen was Du schreibst, weil teilweise Bezugspunkte fehlen, und Du Teilweise komische Begriffe verwendest. Beispielsweise scheinst Du „convert“/„umwandeln“ mit „compile“/„übersetzen“ gleichzusetzen.

Das Du ``200 / 1000`` durch ``0.2`` ersetzen ”musstest” hat auch wieder damit zu tun, dass Du ``cython`` sagen musst das es sich um Python 3 Code handelt, denn bei Python 2 kommt da 0 heraus und nicht 0,2:

Code: Alles auswählen

Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 200 / 1000
0
``cython`` gibt gleich am Anfang eine Warnung aus wenn man nicht explizit zwischen Python 2 und 3 wählt. Das heisst entweder hast Du das falsche ausgewählt, oder gar nichts und die Warnung nicht beachtet.

Bei den Ordnern ging es mir nicht um 3.7 vs. 2.7 sondern um das 'm'. Denn der ”normale” Ordner ist ``/usr/include/python3.7`` und nicht ``/usr/include/python3.7m``. Das dürfte ein Symlink auf den mit 'm' sein, aber das ist ja eher ein Implementierungsdetail. Sicherer ist es den generischen, ohne 'm' zu benutzen. Noch sicherer wäre es den ganzen Kram gar nicht manuell anzugeben, sondern ``python3-config`` zu benutzen, das passt dann nämlich *garantiert* zum installierten Python, auch wenn das ganz woanders liegen würde. Und am allersichersten ist es das alles gar nicht selbst zu machen, sondern einfach ``cythonize`` zu verwenden. Das ist *ein* Aufruf um vom *.py/*.pyx zum compilierten Modul zu kommen.

Wobei die Beschreibungen von dem *was* Du da durch ``cython`` jagst, ja eher nicht nach Kandidaten dafür klingen. GUI-Programme? WTF‽
“All tribal myths are true, for a given value of 'true'.” – Terry Pratchett, The Last Continent
010010
User
Beiträge: 14
Registriert: Freitag 3. Juni 2016, 20:33

Donnerstag 3. Januar 2019, 13:13

Hier mal ein Beispiel für etwas das ohne Probleme Funktionierte.

Python Version von meiner Eingestrichenen Oktave:
Bild

Hier die C Version:
Bild

Das sieht exakt genau so auch in der Konvertierten und dann compilierten Version aus. Macht auch genau das gleiche. Ohne Probleme. Es geht wirklich nur darum das meine Ausgabe im Terminal bei den Layouts nicht läuft und ich noch keine Ahnung habe wie es besser zu machen ist.
Benutzeravatar
__blackjack__
User
Beiträge: 2552
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 3. Januar 2019, 13:20

@010010: Wo das Problem liegt und wie man es löst, wurde ziemlich klar benannt. Du musst ``cython``/``cythonize`` explizit sagen, dass es sich um Python 3-Code handelt der da von Python/Cython nach C übersetzt werden soll, sonst wird der halt als Python 2 Code übersetzt, mit dem beobachteten Verhalten. Und ``cython`` warnt Dich auch selbst schon davor. Bei beiden Abweichungen wurde hier auch gesagt *warum* sich der übersetzte Code so verhält. Ich weiss nicht wie man Dir da noch weiter helfen soll. :K
“All tribal myths are true, for a given value of 'true'.” – Terry Pratchett, The Last Continent
Antworten