Servus,
ich wühle mich gerade in Python ein und hänge fest:
Platform: Win10, XAMPP, Firefox
Ich habe ein PDF auf der Platte und versuche es zu einem Browser zu
senden:
Auf der Kommandozeile kommt das PDF auf sdtout in lesbar,
im Browser kommt ein ellenlanger String aus wahllosen Buchstaben
an den er nicht verarbeiten kann:
JVBERi0xLjQKJeLjz9MNCjMgMCBvYmoKPDwKL0xpbmVhcml6ZWQgMQovTCAyNTg0MAovSCBb
ODI5IDkzXQovTyA1Ci9FIDI1NTI0Ci9OIDEKL1QgMjU3MzkKPj4KZW5kb2JqCnhyZWYKMyAy
NgowMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDA3ODEgMDAwMDAgbg0KMDAwMDAwMDkyMiAw
MDAwMCBuDQowMDAwMDAxNDg3IDAwMDAwIG4NCjAwMDAwMDE1MzUgMDAwMDAgbg0KMDAwMDAw
MTY2NiAwMDAwMCBuDQowMDAwMDAyMjg0IDAwMDAwIG4NCjAwMDAwMDMxMDUgMDAwMDAgbg0K
MDAwMDAwMzI4MyAwMDAwMCBuDQowMDAwMDE4NTk1IDAwMDAwIG4NCjAwMDAwMTg3NTUgMDAw
MDAgbg0KMDAwMDAxOTM5NyAwMDAwMCBuDQowMDAwMDE5Njc3IDAwMDAwIG4NCjAwMDAwMjAz
MDQgMDAwMDAgbg0KMDAwMDAyMDc2NCAwMDAwMCBuDQowMDAwMDIxMTI0IDAwMDAwIG4NCjAw
MDAwMjE1NDMgMDAwMDAgbg0KMDAwMDAyMjU2MiAwMDAwMCBuDQowMDAwMDIyODk0IDAwMDAw
IG4NCjAwMDAwMjMyMDkgMDAwMDAgbg0KMDAwMDAyMzUyOSAwMDAwMCBuDQowMDAwMDIzODE3
IDAwMDAwIG4NCjAwMDAwMjQxMzggMDAwMDAgbg0KMDAwMDAyNDQ2MyAwMDAwMCBuDQowMDAw
MDI0NzQ0IDAwMDAwIG4NCjAwMDAwMDA4MjkgMDAwMDAgbg0KdHJhaWxlcgo8PAovU2l6ZSAy
OQovUm9vdCA0IDAgUgovSW5mbyAyIDAgUgovSURbPGViMTFlM2U0NWU4NWY5NGY5YWE2M2Mz
Mzg0Zjc5MTI2PjxlYjExZTNlNDVlODVmOTRmOWFhNjNjMzM4NGY3OTEyNj5dCi9QcmV2IDI1
NzMxCj4
In C öffne ich das file, ein bißchen malloc, read und dann mit fwrite
raus - kein Problem.
Woran könnte das liegen ?
Du solltest vor der Datei noch einen entsprechenden Header senden damit
der Browser weiß, was er tun soll.
Content-Type application/pdf
Und ggf. noch den passenden Content-Disposition, je nachdem ob du es
inline anzeigen oder Downloaden möchtest.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
Alles andere ist nur Zufall wenn es funktiniert.
Der String ist base64
Joachim D. schrieb:> sys.stdout.buffer.write( b"Content-Type: application/pdf\n\n")
Sorry, gerade erst gesehen.
Ist aber falsch, HTTP-Zeilen enden mit <CR><LF> also \r\n
'\n' ist zulässig.
Wie gesagt, ich bin komplett neu mit Python und verstehe die
(kruden) Gedanken die dahinterstecken, noch nicht.
stdout ist stdout. Wieso codiert Python einen String auf einmal
base64 abhängig davon ob es auf die Kommandozeile oder zum
Indianer geht ?
In der Doku zu sys.stdout.buffer.write() steht, es ginge 1:1
raus. Dann landet das base64 im Browser...
B. W. schrieb:> Hattest du mal eine Version mit base64-encodierung? Dann könnte der> Browsercache zugeschlagen haben.
Keine Ahnung. Könnte sein. Cache habe ich zwischendurch gelöscht.
Das PDF wird bei jedem Abruf neu erzeugt, eigentlich sollte das
nicht aus dem Cache kommen.
@DPA wird der Header vom Apache CGI-parser nicht neu geschrieben?
Joachim D. schrieb:> fd = open( cgi["PDF"], "rb")
Das wartet nur so auf einen Directory-traversal Angriff...
nach der Folgenden zeile ist der QUERY_STRING immer "PDF=jdtmp.pdf",
egal was vom Client kommt, ich bin mir ziemlich sicher das willst du
nicht.
Joachim D. schrieb:> # QUERY_STRING in cgi-Dictionary ablegen> os.environ["QUERY_STRING"] = "PDF=jdtmp.pdf">> cgi = {}
das Iterieren über indexe macht man in Python eigentlich nicht,
Die meisten Objekte, wo es sinnvol ist, bringen einen eigenen iterator
mit.
# don't overwrite exiting key/value pairs, but append new one.
10
cgi.setdefault(key, value.replace( "%20", " "))
> sp = os.environ["QUERY_STRING"].split( "&")> for i in range( len( sp)):> t = sp[i].split( "=")> cgi[t[0]] = t[1].replace( "%20", " ")>> # PDF lesen und abschicken>
Für das Lesen einer Datei sollte man in Python einen Sogenannten Context
manager verwenden, der Gibt die Ressourcen nach dem verlassen selbst
wieder frei (auch bei einer Exception), außerdem kann man dem buildin
print als parameter mitgeben, das es mit '\r\n' die ziele abschließen
soll, aber das ist mein persönlicher still.
Es hat nichts mit Deinem Problem zu tun, aber in einem HTML-Dokument
zweimal dieselbe ID zu vergeben, ist keine gute Idee -- nimm lieber
class="". So eine id sollte ein eindeutiger Bezeichner sein.
> getpdf.py:>>
> [...]> Woran könnte das liegen ?
Bitte entschuldige, aber Dein Python-Skript ist an so vielen Stellen
kaputt... Zum Einen hat Python das Modul "cgi" dabei, daß sich ganz
selbständig um das Parsen und Dekodieren von CGI-Environments kümmern
kann.
Ich hab's nicht getestet, aber das hier scheint mir ein besserer
Ausgangspunkt zu sein (Python 3):
1
#![shebang]
2
import cgi
3
import traceback
4
5
if __name__ == '__main__':
6
form = cgi.FieldStorage()
7
try:
8
with open(form['PDF'], 'rb') as ifh:
9
print('Content-Type: application/pdf')
10
print()
11
sys.stdout.write(ifh.read())
12
except:
13
print('Content-Type: text/plain')
14
print()
15
traceback.print_exc()
Was passiert? Nun, zunächst parst die Klasse cgi.FieldStorage Dein
CGI-Environment in die Variable "form". Die entstandene Instanz der
Klasse cgi.FieldStorage kann dann unter anderem wie ein Dictionary
angesprochen werden, also gibt form["PDF"] (oder form['PDF'], das tut
sich nichts) zurück, was als Query-Parameter "PDF" übergeben worden ist,
in diesem Falle der Dateiname.
Die with-Syntax erzeugt einen eigenen Scope mit einem Objekt "ifh", das
nur in diesem Scope zur Verfügung steht. Diesem Objekt wird zugewiesen,
was der Aufruf hinter dem "with" zurückgibt, in diesem Falle also eine
Instanz der Klasse "_io.BufferedReader". Sobald der Scope verlassen
wird, wird die "magische" Spezialmethode "__exit__()" der Instanz
aufgerufen und dieselbe zerstört, kurz gesagt: mit der with-Syntax
(korrekt: einem Context Manager, also etwas, das die Methode
"__exit__()" hat) kannst Du eine Datei öffnen und sicherstellen, daß sie
korrekt geschlossen wird, wenn der mit "with" eingeleitete Block
verlassen wird.
Außerdem habe ich dort ein -- zugegeben: sehr rudimentäres --
Exception-Handling eingebaut: wenn irgendetwas explodiert, wird die
Exception abgefangen und als PlainText an den Browser zurückgesandt.
Nebenbei bemerkt: ein Browser ist vermutlich nicht das richtige
Werkzeug, um das zu debuggen -- mit curl(1) geht das sicherlich besser,
weil Du dann wirklich präzise sehen kannst, was da über die Leitung
geht. Und dank WSL bzw. dem neuen WSL2 kannst Du curl(1) natürlich auch
ganz einfach installieren und nutzen... ;-)
HTH.
Keine Ahnung von Python, aber zwei Sachen:
Hat stdout bei Windows-Python auch einen text/binär Modus? Eine LF ->
CRLF-Wandlung bei PDFs geht schief.
Ich würde mal zusätzlich zum Content-Type noch ein
"Content-Transfer-Encoding: binary\r\n" mitschicken. Die (vom Browser
nicht verstandene) Base64-Wandlung muß ja wohl der Web-Server machen -
wer weiß, was er da sonst noch anstellt.
Imonbln schrieb:> [code]> try:> # write pdf to caller terminate with '\r\n'> with open(cgi["PDF"], 'rb') as pdf:> print( b'Content-Type: application/pdf', end='\r\n')> # be prepared for huge pdfs> for chk in iter(pdf.read, b''):> print(chk, end='')> print('', end='\r\n')
HTTP trennt Header und Body mit einer Leerzeile, das letzte print('',
end...) muß also hinter das vorherige und vor die for-Loop -- oder das
erste print() kann den Parameter end='\r\n\r\n' setzen und das zweite
print() dann weggelassen werden. Aber, wie schon gesagt, darum sollte
sich auch ein wohlerzogener Webserver kümmern, der Apache tat das IIRC
schon in Version 1.irgendwas.
Mir ist auch schleierhaft, warum der Header "Content-Type" als
Binärstring erzeugt und geschrieben wird... HTTP ist PlainText, oder?
Sheeva P. schrieb:> Mir ist auch schleierhaft, warum der Header "Content-Type" als> Binärstring erzeugt und geschrieben wird... HTTP ist PlainText, oder?
Stimmt, ich habe das vom TO übernommen ohne darüber nachzudenken, ist
etwas her das ich , dass letze mal Http selbst gesprochen habe ohne
frameworks wie flask oder ähnliches.
Btw ich bin mir ziemlich sicher da sind noch andere Http Fehler in
meinen Codefragement, zum Beispiel glaube ich nicht das man nur '%20'
Ersetzen muss. Schon die Wikipedia kennt mehr (siehe
https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_in_a_URI).
imonbln schrieb:> Btw ich bin mir ziemlich sicher da sind noch andere Http Fehler in> meinen Codefragement, zum Beispiel glaube ich nicht das man nur '%20'> Ersetzen muss. Schon die Wikipedia kennt mehr (siehe
Klar. In C gehe ich da durch den String und ersetze
'\xx' durch den Zeichencode $xx. Mit einem Pointer ist
das einfach lösbar. Ohne Pointer fummelig ;)
imonbln schrieb:> zum Beispiel glaube ich nicht das man nur '%20' Ersetzen muss
URL-Kodierung ist eine erstaunlich komplexe und problematische
Geschichte.
Hinter einem % müssen immer 2 Hexadezimale zahlen kommen. Das encodiert
ein Byte. Das mit der Encoding ist bei der URL-Codierung noch ein
bisschen ein durcheinander. Die Teile, die keine %XX sind, nach utf-8
Convertieren falls die nicht schon utf-8 sind, dann alles als byte Array
auffassen, dabei die %XX zu bytes wandeln, und das nachher wieder in nen
utf-8 String Convertieren. Dann müsste das alles decodiert sein. Es gibt
ungültige URLs, z.B. wenn es kein gültiges UTF-8 ist, oder auf ein %
keine 2 hex zahlen folgen. Und Früher waren die URLs glaub ich mal
ASCII, das sorgt heute noch für Probleme, wenn man versehentlich codier
und decodier Funktionen nutzt, die nicht beide von UTF-8 ausgehen, dann
geht das bei Umlauten schief. Kleine JS Demo des Problems:
1
>decodeURIComponent(escape('ä'))
2
VM156:1UncaughtURIError:URImalformed
So oder so, am besten ne Library nehmen, schauen, dass die UTF-8 nimmt,
und Fehler abfangen.
Jetzt habe ich mir das Programmieren endgültig versaut:
Ständig 'printf' statt 'print' und retour, dann noch die Sache mit dem
';' ;)
Danke nochmal für die Tipps !
Joachim D. schrieb:> Klar. In C gehe ich da durch den String und ersetze> '\xx' durch den Zeichencode $xx. Mit einem Pointer ist> das einfach lösbar. Ohne Pointer fummelig ;)
In Python ist das sogar noch einfacher, weil Objekte der Typen str und
byte iterable und subscribable sind. Außerdem gehört zum Standardumfang
von Python natürlich eine leistungsfähige Bibliothek für reguläre
Ausdrücke.
Joachim D. schrieb:> Jetzt habe ich mir das Programmieren endgültig versaut:>> Ständig 'printf' statt 'print' und retour, dann noch die Sache mit dem> ';' ;)>> Danke nochmal für die Tipps !
Du kannst das ';' auch in Python schreiben, das tut ihm nichts. Und wenn
Du in Python statt print() lieber printf() schreiben möchtest, nichts
einfacher als das:
Ich stolpere schon per RegEx über den Kommentar am Anfang.
Die Datei ist in C recht einfach auszuwerten. Sie enthält in
der Praxis ca 60 Benutzergruppen und ca 12000 User. Dauert
in C 0.01 sec. Das dürfte mit einem Interpreter nicht zu
erreichen sein.
Um den Kommentar am Anfang auszumerzen suche ich ein Zeichen
';' am Beginn und ein Zeichen '\n' bzw '\r\n' als letztes und
fülle den Bereich mit ' '. Es will nicht. Vermutlich scheitert
es an den ' '. Ich bin noch am probieren ...
Joachim D. schrieb:> Interessant ... ;)
Langsam beschleicht mich das Gefühl, daß Du eher nach Gründen dafür
suchst, warum C "besser" (für beliebige Definitionen von "besser") sein
soll als Python. Denn kaum bekommst Du eine Antwort für das jeweils
geschilderte Problem, poppst Du mit dem nächsten Problem auf -- nicht
ohne den Hinweis, daß das in C ja ganz einfach ist, und natürlich
unbedingt performanter als in Python.
Zwischendurch zudem Deine Aussage, hinter Python stünden "(krude)
Gedanken" die Stringbehandlung sei "sehr gewöhnungsbedürftig". Klar, was
man nicht versteht, mag einem erst einmal "krude" erscheinen, aber ob
man damit in einem öffentlichen Forum hausieren gehen sollte? Ich weiß
ja nicht...
Besonders ulkig finde ich übrigens den Hinweis auf Pythons
"gewöhnungsbedürftige" Stringbehandlung vor dem Hintergrund, daß C weder
Strings noch ein Stringhandling kennt, sondern nur nullterminierte
Arrays und ein paar Funktionen, die damit mal mehr, mal weniger gut
umgehen können, ich sag nur strcpy(3) und strncpy(3) -- und erlaube mir
den Verweis auf die etlichen Pufferüberläufe nicht zuletzt auch wegen
fehlerhaften Stringvalidierungen, die auch erfahreneren C-Entwicklern
bisweilen unterlaufen und für die die CVE mannigfaltige Zeugnisse
bereithalten.
Sei mir nicht böse, aber wenn Du Python nicht lernen willst und von
vorneherein eine Aversion gegen Skriptsprachen im Allgemeinen oder gegen
Python im Besonderen hast, dann verstehe ich nicht, was das Ganze hier
soll. Und wenn Du Python lernen willst, verstehe ich nicht, warum Du es
immer wieder mit einer vollkommen anderen Sprache auf einer vollkommen
anderen Höhe und mit vollkommen anderen Paradigmen vergleichst und dann
obendrein auch noch, nunja, vollmundige Urteile über verschiedene
Aspekte der Sprache Python äußerst.
Wenn Du das wirklich willst, dann lern' Python doch erstmal mindestens
bis zu einem halbwegs fundierten Anfängerniveau und schreib ein paar
reale Programme damit, bevor Du solche Urteile herausposaunst. Dann
wirst Du nämlich schnell feststellen, daß es sehr gute Gründe dafür
gibt, warum Python in den einschlägigen Indizes mittlerweile zur
beliebtesten Sprache avanciert ist und sogar den langjährigen
Spitzenreiter Java überholt hat...
> Mit den RegEx habe ich auch probiert, folgende Datei auszuwerten:>>
1
>;rights.d:modified02.03.17/07:29:24
2
>
3
>;(1)Benutzergruppen
4
>
5
>groupGRUPPEA{
6
>testip
7
>tb.docs(readviewgaps)
8
>tb.notes(readview)
9
>tb.system(uquery.exe)
10
>...
11
>exec.system(uslist.exeupass.exeudquery.exe
12
>uinfo.exeusquery.exeuuser.exe)
13
>}
14
>
15
>userjd{
16
>abt()
17
>name(JoeDrechsel)
18
>pass($abeccf9ae147d85436534371f961c95b)
19
>mail()
20
>expd(01.01.2020)group(adminall)
21
>filter()}
22
>
>> Ich stolpere schon per RegEx über den Kommentar am Anfang.
Ist nicht wahr, ernsthaft? Dann empfehle ich die Lektüre von "Regular
Expressions" von Jeffrey Friedl. Aber dafür braucht man natürlich keine
RegEx, das geht einfach mit "line.strip().startswith(';')".
> Die Datei ist in C recht einfach auszuwerten. Sie enthält in> der Praxis ca 60 Benutzergruppen und ca 12000 User. Dauert> in C 0.01 sec. Das dürfte mit einem Interpreter nicht zu> erreichen sein.
Na und? Muß es denn so schnell sein, ist das Dein wichtigstes Kriterium?
Dann solltest Du Deinen Parser vielleicht direkt in Assembler
implementieren, wenn Performanz so überaus wichtig ist. Aber ach, die
Entwicklungszeit...
Nebenbei habe ich mir Deine Datei (was für ein irrsinniges Format, wer
denkt sich sowas aus? Noch nie was von CSV, JSON, oder YAML gehört?)
jetzt einmal spaßeshalber vorgenommen und sie mit RegExen geparst. Das
dauert auf meinem alten Q9650 ungefähr 0.0022 Sekunden inklusive
Einlesen der Datei -- die Startzeiten von Python habe ich dabei
allerdings einfach mal herausgelassen. Nicht schlecht für langsame
RegExen in einer langsamen Skriptsprache, nicht wahr?
Der Hashwert für das Benutzerpaßwort erscheint mir ziemlich kurz,
womöglich könnte man da womöglich mal auf eine modernere Variante wie
SHA gehen... zudem ist es heute eine gängige Praxis, auch einen Hinweis
auf die Hashfunktion zu speichern, damit sie an neue Anforderungen
angepaßt werden kann.
> Um den Kommentar am Anfang auszumerzen suche ich ein Zeichen> ';' am Beginn und ein Zeichen '\n' bzw '\r\n' als letztes und> fülle den Bereich mit ' '. Es will nicht. Vermutlich scheitert> es an den ' '. Ich bin noch am probieren ...
Dafür brauchst Du keine RegExe, da reicht das "gewöhnungsbedürftige
Stringhandling" von Python: line.strip().startswith(';'). Das findet
sogar Kommentarzeilen, bei denen vor dem Semikolon noch Whitespace
steht. Per RegEx wäre es r'^\s*?\;.*$' mit Leerzeichen vorm Semikolon,
ansonsten kannst Du das '\s*?' am Anfang weglassen.
Danke. Und gleichzeitig bitte ich um Nachsicht.
Ich lebe seit über 35 Jahren in C, das ist jetzt mal so der erste
Ausflug in so etwas "objektorientiertes" und ich weiß, da bin
ich noch ziemlich am Anfang (nebenbei, der Regex-Parser ist in C
geschrieben).
Mit fehlt da noch der Überblick. Finde ich in der Standard-C-Lib
keine brauchbare Strringfunktion baue ich die halt schnell selbst.
So habe ich eine Unzahl an Funktionen.
line.strip().startswith(';') ok, wo finde ich was line kann ?
Da hängt es bei mir schon. Ich wühle mich durch die Websites die
irgendwas mit "Python" haben und stopple mir halt das zusammen.
Ich fange halt damit an, meine C-Sachen in Python zu probieren.
Nicht lebensnotwendig, halt interessant.
Joachim D. schrieb:> Ich lebe seit über 35 Jahren in C, das ist jetzt mal so der erste> Ausflug in so etwas "objektorientiertes" und ich weiß, da bin> ich noch ziemlich am Anfang
Beschwer dich einfach nicht und stell keine Vergleiche an - in Features
schlägt Python C immer, aber vielleicht oft nicht immer in Performanz
und die Syntax ist teilweise gewöhnungsbedürftig, das gleiche würde dir
aber auch und schlimmer mit Schwester C++ passieren - und Doku und
Beispiele lesen ist der Schlüssel, btw kannst du jeden deiner C
Algorithmen so auch in Python implementieren
Das wird schon noch. "Damals" mit C anzufangen war viel
schlimmer (da stand die ersten 2 Wochen der PC mehrmals
kurz davor aus dem Fenster zu fliegen).
Python ist recht mächtig - aber hauptsächlich aufgrund
seiner Zusatzmodule, die gibt es für C aber auch.
Das war jetzt aktuell nicht der Grund mich damit zu
beschäftigen. Eher "mal was Neues" und "wegen Corona ja
auch mal Zeit".
Einige Programme habe ich schon mit C++ gemacht, habe mal
mit Assembler (6502,8088, Z80) angefangen und auch Hexdumps
aus der mc abgetippt. Dann noch Pascal (sehr geschwätzig) und
dBase 3 und 4.
An Python finde ich den Funktionsumfang interessant, auch
daß sie mal eine ganz andere Optik des Quellcodes verwenden.
Ist halt mal was anderes ;)
cppbert schrieb:> in Features schlägt Python C immer
Nein. Es gibt viele Features, die nur C hat. Das fängt unter anderem mit
der statischen typisierung an, und geht mit allen Konstrukten weiter,
die damit möglich werden. Immer wieder toll, sind die dadurch
entstehenden Runtimefehler in python. Vertippt man sich in c bei einer
Variable oder einer Funktion, bricht es gleich beim Kompilieren schon
ab, und sagt einem wo man den Fehler gemacht hat. Python läuft erstmal
einfach los, und trifft die fehlerhafte stelle dann vielleicht später
irgend wann mal. Noch besser ist das vertippen beim Setzen einer
Variablen, das macht Python doch gerne!
Joachim D. schrieb:> Danke. Und gleichzeitig bitte ich um Nachsicht.
Oh, nix für ungut... entschuldige bitte, war halt nur so ein Gefühl.
> Ich lebe seit über 35 Jahren in C, das ist jetzt mal so der erste> Ausflug in so etwas "objektorientiertes" und ich weiß, da bin> ich noch ziemlich am Anfang (nebenbei, der Regex-Parser ist in C> geschrieben).
Ein sehr großer Teil der Python-Bibliotheken ist in C oder in C++
geschrieben, das gilt gleichermaßen für die gemeinhin mitgelieferten
Standardlibraries, aber auch für externe Libraries wie numpy, und mit
Python3 sind es sogar noch viel mehr. Deswegen ist Python oft
ausgesprochen performant zur Laufzeit, hat gleichzeitig aber die großen
Vorteile einer Skriptsprache bei der Entwicklungszeit und der
Codedichte.
> Mit fehlt da noch der Überblick. Finde ich in der Standard-C-Lib> keine brauchbare Strringfunktion baue ich die halt schnell selbst.> So habe ich eine Unzahl an Funktionen.
In Python bringen die Klassen str und bytes bereits eine riesige Menge
an Funktionen mit, mit "pydoc str" und "pydoc bytes" findest Du die
Dokumentation dazu.
Eine der vielen Stärken von Python ist halt seine Infrastruktur, das
betrifft die mitgelieferten Standardbibliotheken -- in denen schon viele
fertige, getestete und performanceoptimierte Bibliotheken, Module und
Frameworks vorhanden sind -- aber auch die unglaublich vielen
verfügbaren Third-Party-Bibliotheken, die über ein zentrales Repository
mit dem Paketmanager pip ganz einfach installiert werden können. Um zum
Beispiel CSV-- oder JSON-Dateien zu lesen, muß ich mir in C, C++ und
Java jeweils eine passende Bibliothek suchen (und sie nicht selten auch
testen...), während Python für soetwas bereits fertige Bibliotheken mit
den (vollkommen überraschenden) Namen csv und json mitliefert. Und
(siehe oben) auch für CGIs...
Bitte behalte das immer im Hinterkopf, bevor Du selbst etwas
implementierst. Ich habe schon etliche Python-Einsteiger gesehen, die
sich selbst was zusammengeprokelt haben, das Python schon fertig
mitgeliefert hat oder zumindest im PyPi, also dem zentralen
Python-Paketrepository, vorhanden war.
> line.strip().startswith(';') ok, wo finde ich was line kann ?
Oh... bitte entschuldige, line ist in diesem Falle ein String bzw. eine
Instanz der Klasse str. Das liegt daran, daß man in Python ganz einfach
zeilenweise über eine Datei iterieren kann, entweder mit
1
f = open('datei.txt', 'r')
2
for line in f:
3
if line.strip().startswith(';') or line.strip() == '': next
4
print(line)
5
f.close()
oder, noch etwas schicker und moderner, mit einem Contextmanager:
1
with open('datei.txt', 'r') as f:
2
for line in f:
3
if line.strip().startswith(';') or line.strip() == '': next
4
print(line)
Beide Codebeispiele öffnen eine Datei namens "datei.txt" im Lesemodus
('r') und liest diese Zeilenweise in die Variable "line", die also
einfach nur eine Instanz der Klasse str ist und damit alle Methoden und
andere Möglichkeiten bietet, die diese Klasse hat und die Du mit "pydoc
str" nachlesen kannst. Und, ach ja: über einen str() kannst Du natürlich
wieder mit einer Schleife iterieren...
Denn eine der eigentlichen Stärken von Python liegt noch einmal
woanders, ist aber nicht ganz einfach zu erklären -- ich versuche es
trotzdem mal. Also, Python kennt neben konkreten eingebauten ("pydoc
builtins") und selbstdefinierten Klassen (also Datentypen) auch noch
bestimmte... Schnittstellen dafür, zum Beispiel Iterable oder Sequence
-- und lustigerweise kann ein Iterable auch eine Sequence sein.
Ein iterable, um bei diesem Beispiel zu bleiben, kann vieles sein: zum
Beispiel eine Datei, wie in den beiden Codebeispielen oben, oder auch
eine list(), ein tuple(), ein str() oder eine selbstdefinierte Klasse,
wenn diese die "magischen" Methoden __iter__() und __next__() definiert.
Anders gesagt: ob eine Klasse eine bestimmte Schnittstelle
implementiert, hängt von den Methoden ab, die sie... ach stimmt, das ist
in anderen Sprachen wie Java & Co ja ganz ähnlich. ;-)
Diese "magischen" Methoden, deren Name mit zwei Unterstrichen beginnt
und endet, sind die Grundlage für viele spannende Dinge, die man mit
Python machen kann, vom Überladen von Operatoren bis hin zu bestimmten
Charakteristiken, die man seinen eigenen Klassen verleihen kann -- wie
eben Iterable.
Das Lustige dabei ist, das ein großer Teil der Python-Standardbibliothek
bereits darauf ausgelegt sind, mit diesen Schnittstellen zu arbeiten.
Zum Beispiel gibt es in der random-Bibliothek eine Funktion choice(),
die zufällige Elemente aus einer Sequence auswählt:
1
import random
2
3
# Eine Liste von Zeichen (könnte auch eine von Strings sein...)
4
s = ['a', 'b', 'c']
5
print(random.choice(s))
6
7
# ein str(), ebenfalls eine Sequence
8
s = 'abc'
9
print(random.choice(s))
10
11
# Datei zeilenweise in eine list() lesen
12
with open('datei.txt', 'r) as ifh: s = ifh.readlines()
13
print(random.choice(s))
14
15
# Datei zeichenweise in eine list() lesen
16
with open('datei.txt', 'r) as ifh: s = ifh.read()
17
print(random.choice(s))
Die Variable s enthält hier jeweis eine Sequence: einmal eine list() aus
Zeichen, dann einen str(), dann eine list() von Zeilen in einer Datei
und dann eine list() von Zeichen in einer Datei.
> Da hängt es bei mir schon. Ich wühle mich durch die Websites die> irgendwas mit "Python" haben und stopple mir halt das zusammen.>> Ich fange halt damit an, meine C-Sachen in Python zu probieren.> Nicht lebensnotwendig, halt interessant.
Statt dieser Vorgehensweise empfehle ich eher eine klassische: Bücher.
Gerade für Python gibt es viel herausragende Lektüre, vor allem beim
Verlag O'Reilly. Meine Empfehlung wäre, mit der Einführung zu beginnen,
die findest Du in "Learning Python", das es als "Einführung in Python"
auch auf Deutsch gibt. Die sinnvollsten Folgelektüren wären wohl
"Programming Python" und natürlich das "Python Cookbook", damit kommst
Du schon sehr, sehr weit. Für erfahrene Pythonistas sind IMO "Fluent
Python" und "High-Performance Python" gut geeignet, und ansonsten gibt
es -- immer je nachdem, was Du mit Python machen möchtest --
entsprechende Fachliteratur von Büchern über numpy und scipy über Pandas
für Datenfresser, Flask und Django für Webentwickler, und und und...
Joachim D. schrieb:> Das wird schon noch. "Damals" mit C anzufangen war viel> schlimmer (da stand die ersten 2 Wochen der PC mehrmals> kurz davor aus dem Fenster zu fliegen).>> Python ist recht mächtig - aber hauptsächlich aufgrund> seiner Zusatzmodule, die gibt es für C aber auch.
Naja... aber für C, C++ und Java mußt Du Dir 90 Prozent dessen, was
Python bereits standardmäßig mitliefert, erstmal mühsam zusammensuchen,
die Lizenz überprüfen, und testen. Und von den übrigen 10 Prozent gibt
es 99 Prozent leider gar nicht für C oder C++ (think Pandas, Flask,
Django, Matplotlib, Bokeh, ...), das mußt Du Dir dabei aus drölfzig Libs
richtig mühsam zusammenstoppeln und -basteln. ;-)
DPA schrieb:> cppbert schrieb:>> in Features schlägt Python C immer>> Nein. Es gibt viele Features, die nur C hat. Das fängt unter anderem mit> der statischen typisierung an, und geht mit allen Konstrukten weiter,> die damit möglich werden.
Das bieten andere statisch typisierte Sprachen wie C++ und Java auch an,
zum Teil erheblich ausgereifter und sicherer als in C. Erfreulicherweise
bietet Python aber eine Introspektion an, wie leo oben mit seinem
type()-Aufruf gezeigt hat und mit isinstance(), Type Hints ("def
funktion(name: str)") und weiteren Methoden prima unterstützt.
Und dann ist es halt immer die Frage, welche Art von Interpreter gerade
benutzt wird. Für Python gibt es da beispielsweise die
Referenzimplementierung CPython, welche -- wie viele
Skriptspracheninterpreter -- zunächst den Sourcecode nimmt, diesen in
ausführbaren Bytecode umwandelt, und den Bytecode dann ausführt. Dann
können viele Fehler bereits zur Entwicklungszeit gefunden werden.
Es gibt aber auch den Interpreter Pypy, der Just-In-Time (JIT)
kompiliert und deswegen natürlich auch keine Fehler zur Entwicklungszeit
finden kann, weil er natürlich immer nur den Code übersetzt, der gerade
zur Ausführung ansteht. Aber dafür ist dieser Interpreter in vielen
Anwendungsfällen extremst performant, vor allem natürlich wenn viele
Bedingungen oder Schleifen durchlaufen werden müssen.
Natürlich gibt es auch Jyton und Ironpython, aber ich bin jetzt zu faul
(oder habe im Falle von Ironpython kein Windows zum Ausprobieren), um zu
schauen, wie die mit solchen Fehlern umgehen. Aber es gibt
selbstverständlich immer die Möglichkeiten, Python in C- oder C++-Code
zu übersetzen, mit nuitka [1] zum Beispiel. Und zudem existieren noch
eine Reihe von Code-Checkern wie etwa pylint...
Ganz am Rande bemerkt: mir ganz persönlich ist es wesentlich lieber,
wenn meine Programme zur Laufzeit mit einer aussagekräftigen
Fehlermeldung abstürzen, als daß ich mir einen Buffer Overflow
einhandele, der es einem Angreifer ermöglicht, meine Systeme zu
übernehmen. YMMV.
Python ist übrigens, entgegen eines weitverbreiteten Irrglaubens,
tatsächlich stark, jedoch dynamisch typisiert: der Typ einer Variable
ist nicht an ihren Namen, sondern an ihren Wert gebunden.
> Immer wieder toll, sind die dadurch> entstehenden Runtimefehler in python. Vertippt man sich in c bei einer> Variable oder einer Funktion, bricht es gleich beim Kompilieren schon> ab, und sagt einem wo man den Fehler gemacht hat. Python läuft erstmal> einfach los, und trifft die fehlerhafte stelle dann vielleicht später> irgend wann mal. Noch besser ist das vertippen beim Setzen einer> Variablen, das macht Python doch gerne!
Ach ja, Daniel, das sind eben die typischen Unterschiede zwischen einer
dynamisch, aber stark typisierten Skriptsprache wie Python, einer
schwach typisierten Sprache wie Perl, und einer statisch kompilierten
Sprache wie C, C++ oder Java. In Perl und PHP ergibt die Addition von
"'4' + 3" tatsächlich 7, in Python und Ruby jedoch eine (abfangbare)
Exception.
Nebenbei bemerkt, kann ich in jeder Spache Bullshit schreiben. Das als
Argument für oder wider Spriptsprachen zu benutzen, halte ich aber für
noch größeren Bullshit, denn letztlich haben beide Familien ihre
spezifischen Vor- und Nachteile. Aber daß ein Entwickler Mist macht...
meine Güte, soll das wirklich ein Argument sein? ;-)
Sheeva P. schrieb:> Statt dieser Vorgehensweise empfehle ich eher eine klassische: Bücher.
Natürlich. Im Moment lese ich da online einiges, es sind halt
"Einführungen" (dh: "mein erstes Programm" uÄ) (Nebenbei: die
Byers Übersetzungen / Neuschreibungen bei Vieweg über dBase IV
waren von mir).
Ich hänge an der "Idee" Pythons. zB warum die Unterscheidung
zwischen str (String) und byte (auch String). Ich verstehe den
Sinn dahinter nicht.
Python selbst mag etwas lahm sein, allerdings sind die meisten
Module in C geschrieben und die Befehle/Kommandos sehr mächtig.
Das relativiert das "lahm" ;)
Ich denke halt "wie geht das in C" und versuche so, das was
Python da gerade macht, nachzuvollziehen.
Wird noch ein wenig dauern, irgendwann macht es dann "klick".
Sheeva P. schrieb:> "Learning Python"
Ich werde mir das besorgen.
Vielen Dank an alle !
Sheeva P. schrieb:> DPA schrieb:>> cppbert schrieb:>>> in Features schlägt Python C immer>>>> Nein. Es gibt viele Features, die nur C hat. Das fängt unter anderem mit>> der statischen typisierung an, und geht mit allen Konstrukten weiter,>> die damit möglich werden.>> Das bieten andere statisch typisierte Sprachen wie C++ und Java auch an,> zum Teil erheblich ausgereifter und sicherer als in C.
Ja schon, aber es ging nun mal um python und c.
> Erfreulicherweise> bietet Python aber eine Introspektion an, wie leo oben mit seinem> type()-Aufruf gezeigt hat und mit isinstance(),
Das ist aber etwas komplett anderes. Introspektion gibt es zu einem
gewissen Grad auch in c. sizeof, offsetof, alignof _Generic,
static_assert, etc. Zwar nur zur compile-time, und nicht ganz so toll
wie in einigen anderen statisch typisierten Sprachen, aber definitiv
vorhanden. An Java sieht man, das statische Typisierung und Runtime
Introspektion sich auch nicht ausschliessen, aber man kann halt nicht
alles haben.
> Type Hints ("def> funktion(name: str)") und weiteren Methoden prima unterstützt.
Oh, type hints kannte ich noch nicht. Seit python 3.5, ist wohl relativ
neu. Das ist zumindest mal ein Anfang. Ist aber immer noch nur ein
runtime-check.
Sheeva P. schrieb:>> Immer wieder toll, sind die dadurch>> entstehenden Runtimefehler in python. Vertippt man sich in c bei einer>> Variable oder einer Funktion, bricht es gleich beim Kompilieren schon>> ab, und sagt einem wo man den Fehler gemacht hat. Python läuft erstmal>> einfach los, und trifft die fehlerhafte stelle dann vielleicht später>> irgend wann mal. Noch besser ist das vertippen beim Setzen einer>> Variablen, das macht Python doch gerne!>> Ach ja, Daniel, das sind eben die typischen Unterschiede zwischen einer> dynamisch, aber stark typisierten Skriptsprache wie Python, einer> schwach typisierten Sprache wie Perl, und einer statisch kompilierten> Sprache wie C, C++ oder Java.
Python würde ich aber nicht als stark Typisiert betrachten. Mit
TypeScript gibt es eine Scriptsprache, die zwar auch kompiliert wird,
und schon vor der Ausführung Typfehler und ähnliches finden kann, aber
trotzdem nicht wirklich statisch ist. Das würde ich als stark Typisiert
betrachten. Vielleicht bekommen wir ja irgendwann mal ein Python 4 oder
so, wo das endlich mal besser wird ;)
> In Perl und PHP ergibt die Addition von> "'4' + 3" tatsächlich 7, in Python und Ruby jedoch eine (abfangbare)> Exception.
In C ergibt Pointer + Integer -> Pointer. Ich sehe nicht, was das mit
Statischer vs. Dynamische Typisierung zutun haben soll.
Sheeva P. schrieb:> Nebenbei bemerkt, kann ich in jeder Spache Bullshit schreiben.
Klar kann man in allen Sprachen Bullshit schreiben. Aber in C muss man
es wenigstens formal-richtig falsch programmieren. Diese Art von Fehler
sieht man halt in C sofort, und in Python nicht. Es ist und bleibt ein
Vorteil und ein Feature, das Python nicht hat. Und doch, das ist ein
sehr gutes Argument gegen Python und co. Mein Argument beschränkte sich
auch nicht nur auf die Fehler, die man so finden kann. Zur Compiletime
Code generieren, im Vornherein wissen, das Methoden und Membervariablen
da sind, den richtigen Type haben, Gross genug sind, die die Annahmen
schon vor dem Ausführen checken, das geht halt in Python alles nicht
oder nicht so einfach.
Und damit kommen wir wieder zu dem, worum es in dem Argument eigentlich
ging. cppbert behauptete, in Features schlage Python C immer. Aber da es
zwangsläufig Features in C gibt, die Python in der jetzigen Form nicht
haben kann, kann das nicht stimmen.
> Das als> Argument für oder wider Spriptsprachen zu benutzen, halte ich aber für> noch größeren Bullshit, denn letztlich haben beide Familien ihre> spezifischen Vor- und Nachteile.
Es geht mir nicht darum zu sagen, C wäre besser als Python, sondern
darum, dass die Implikation, Python sei besser als C, genauso falsch
ist.
Abgesehen davon, klar haben beide Familien ihre spezifischen Vor- und
Nachteile. Nur deshalb ist es noch lange kein Bullshit, mal von einer
Seite welche hervorzuheben, wenn es nötig wird. Wenn man alle Vor und
Nachteile von Sprachen einfach als irrelevanter Bullshit abtut, wird es
doch absolut Sinnfrei, über diese Argumentieren zu wollen.
DPA schrieb:> Es geht mir nicht darum zu sagen, C wäre besser als Python, sondern> darum, dass die Implikation, Python sei besser als C, genauso falsch> ist.
Das ist auch unwichtig.
Da könnte man auch argumentieren; Phyton ist in C geschrieben,
dann nehme ich gleich das Original ;)
Ich denke, das wird sich ergänzen. In C zB eine Mail senden
gibt locker 80 Zeilen Code, in Phyton sind es 2. Natürlich nur
einmal Arbeit (kann man ja wiederverwenden).
Mal schnell 10 GB an Daten irgendwo einsortieren dürfte unter
C erheblich schneller gehen.
SQLite geht auch unter Python.
Die Sachen die ich kenne und brauche sind alle vorhanden, ich
muß sie nur finden ...
Vorweg: Entschuldige bitte, aber was soll denn das sein? Ich vermisse
Dein sonst so viel höheres Niveau.
Tatsächlich wirfst Du Python im Kern vor, daß es eine interpretierte
Programmiersprache ist, wodurch ein separater Kompilationsschritt, in
dem die Typen geprüft werden könnten, wegfällt. Wie unsinnig das ist,
erkennst Du sofort, wenn Du C anstatt mit einem Compiler mit einem der
verfügbaren C-Interpreter Ch, picoc oder tcc ausführst: sobald C nicht
kompiliert, sondern stattdessen interpretiert wird, ist das Verhalten
bei Typfehlern exakt dasselbe wie bei Python: der Interpreter steigt
zur Laufzeit aus. Huch!
Weder die statische Typisierung, noch deren Prüfung in einem separaten
Kompilationsschritt sind also Kernfeatures von C, sondern einer ganzen
Sprachfamilie, nämlich der Sprachfamilie der kompilierten Sprachen und
das auch nur dann, wenn sie kompiliert statt interpretiert werden. In
C's großem Bruder C++, das ebenfalls wesentlich mehr Features anbietet
als C, in Java und auch in Golang ist das alles nämlich genauso; dabei
handelt es sich also offenbar nicht um eine besondere Eigenschaft von
C, sondern ganz allgemein um eine Eigenschaft von statisch typisierten
und kompilierten Programmiersprachen. Python hingegen ist weder das
Eine noch das andere; Python ist aber eine dynamisch stark typisierte,
interpretierte Sprache.
Trotzdem ist Python, entgegen Deines Irrglaubens, stark typisiert; ein
Konstrukt wie die Addition eines String mit einer Integer läßt es also
nicht zu, sondern wirft eine Exception. Das ist etwas anderes als die
inhärente (und reichlich fehleranfällige) Zeigerarithmetik in C, die
Du unsinnigerweise als Beispiel zur Typisierung anführst -- und Deine
Argumentation für C's Typsicherheit selbst widerlegst. Übrigens, wo
Du Dich gerade über Laufzeitfehler ausgelassen hast: eine fehlerhafte
Zeigerarithmetik in C führt regelmäßig zu Laufzeitfehlern, und häufig
sogar zu überaus gefährlichen. Sich ausgerechnet über Programmier- und
Laufzeitfehler in Python zu beschweren und dann gleichzeitig eine der
fehleranfälligsten Laufzeitfehlerquellen in C als Argument zu bringen,
erscheint mir schon ein wenig absurd.
Schwach typisierte Sprachen wie Perl oder PHP hingegen lassen es zu,
Strings und Integers zu addieren. Das führt nicht selten zu logischen
Fehlern, die besonders schwer zu debuggen und zu finden sind, wie ich
aus eigener leidvoller Erfahrung mit beiden Sprachen weiß.
Python dagegen bietet seit fünf Jahren -- okay, der erste Vorschlag
für Type Hints ist von 2006, eingeführt wurden sie aber erst in der
Version 3.5, die vor fünf Jahren released wurde -- tatsächlich die
Möglichkeit, Typsicherheit zu gewährleisten. Prinzipbedingt geschieht
dies jedoch (erinnere Dich: es ist eine interpretierte Skriptsprache)
nicht zur Laufzeit, sondern mit einem separaten Typechecker (hierzu
verwende ich mypy(1) und pylint(1)). Wenn Du statische Typsicherheit
also wirklich haben willst, geht das auch in Python.
Soviel zum Vorwort, im Weiteren möchte ich gerne noch auf ein paar
besondere Passagen Deines Beitrages eingehen.
DPA schrieb:> Sheeva P. schrieb:>> DPA schrieb:>>> cppbert schrieb:>>>> in Features schlägt Python C immer>>>>>> Nein. Es gibt viele Features, die nur C hat. Das fängt unter anderem mit>>> der statischen typisierung an, und geht mit allen Konstrukten weiter,>>> die damit möglich werden.
Welche "Konstrukte" sollten das denn bitte sein? In C++ hätte ich ja
noch verstanden, wenn es im die Überladung von Methoden und Funktionen
geht, aber in C? Und von welchen anderen "Features" redest Du?
>> Erfreulicherweise>> bietet Python aber eine Introspektion an, wie leo oben mit seinem>> type()-Aufruf gezeigt hat und mit isinstance(),>> Das ist aber etwas komplett anderes. Introspektion gibt es zu einem> gewissen Grad auch in c. sizeof, offsetof, alignof _Generic,> static_assert, etc. Zwar nur zur compile-time, und nicht ganz so toll> wie in einigen anderen statisch typisierten Sprachen, aber definitiv> vorhanden. An Java sieht man, das statische Typisierung und Runtime> Introspektion sich auch nicht ausschliessen, aber man kann halt nicht> alles haben.
Echt jetzt, Du willst mir sizeof() & Co als Reflexion bzw. Introspektion
verkaufen? Das ist hoffentlich nicht Dein Ernst. Kannst Du damit denn
zum Beispiel herausfinden, welche (oder auch nur wieviele) Variablen
eine struct enthält? (Übrigens: wenn ich mich jetzt auf das Niveau von
Deiner Argumentation begeben würde, dann würde ich auch noch fragen,
wie Du die Methoden eines Objekts zur Laufzeit herausfinden kannst.)
Und ja, natürlich kann man alles haben, statische Typisierung und auch
Reflexion mit Introspektion. C++, Java und Golang machen ja vor, daß
das nicht nur besser, sondern auch wesentlich typsicherer geht als in
C. Und dann kommt auch noch erschwerend hinzu, daß C dank seines Typs
void leider gar nicht so typsicher ist, wie Du es darstellst.
> Python würde ich aber nicht als stark Typisiert betrachten.
Zum Glück hält sich der Rest der Welt an die üblichen Definitionen,
was starke und schwache Typisierung sind (oder auch, was Reflextion
und Introspektion sind). Und nach diesen Definitionen ist Python nun
einmal stark und dynamisch typisiert.
> Sheeva P. schrieb:>> Nebenbei bemerkt, kann ich in jeder Spache Bullshit schreiben.>> Klar kann man in allen Sprachen Bullshit schreiben. Aber in C muss man> es wenigstens formal-richtig falsch programmieren. Diese Art von Fehler> sieht man halt in C sofort, und in Python nicht.
Natürlich muß man in Python ebenfalls formal korrekt programmieren --
und leider ist es nicht richtig, daß man formale Fehler in C sofort
sieht. Tatsächlich sieht man formale Fehler nämlich erst, wenn man
seinen Code kompiliert -- sei es im Normalfall durch Aufruf eines
Compilers, oder durch Aufruf eines der genannten C-Interpreter. Das
kann man in ähnlicher Form aber auch mit den bereits erwähnten Tools
pylint(1) und mypy(1) unter Python haben.
> Es ist und bleibt ein Vorteil und ein Feature, das Python nicht hat.
Wie gesagt und gezeigt, gibt es das Feature, => kein Vorteil für C.
> Und doch, das ist ein> sehr gutes Argument gegen Python und co. Mein Argument beschränkte sich> auch nicht nur auf die Fehler, die man so finden kann. Zur Compiletime> Code generieren, im Vornherein wissen, das Methoden und Membervariablen> da sind, den richtigen Type haben, Gross genug sind, die die Annahmen> schon vor dem Ausführen checken, das geht halt in Python alles nicht> oder nicht so einfach.
Methoden? Membervariablen? In C? Übrigens: ich habe gezeigt, daß es
das Feature auch in Python gibt, womit Dein "sehr gutes Argument gegen
Python und co." zweifellos entkräftet ist.
> Und damit kommen wir wieder zu dem, worum es in dem Argument eigentlich> ging. cppbert behauptete, in Features schlage Python C immer. Aber da es> zwangsläufig Features in C gibt, die Python in der jetzigen Form nicht> haben kann, kann das nicht stimmen.
Also, nochmal: statische Typisierung geht auch in Python, ob Du das
nun wahrhaben willst oder nicht. Und damit erschöpfen sich die tollen
Features von C dann auch schon. C alleine, also ohne die Funktionen
seiner Standardbibliotheken oder zumindest des Betriebssystemkernels,
kann nämlich so ziemlich gar nichts, nichtmal eine Eingabe aus einer
Datei oder von Standard-Input lesen (dazu braucht es mindestens die
Funktionen open(2), read(2) und close(2), die alle Systemfunktionen
sind, oder die Bibliotheksfunktionen fopen(3), fread(3), fclose(3),
die ihrerseits Funktionen aus der Standardbibliothek sind).
Und selbst mit der Standardbibliothek ist C noch ziemlich arm, wenn es
um den Funktionsumfang geht. Multithreading? Fehlanzeige, dazu braucht
es die externe pthread-Bibliothek. Strings? Fehlanzeige, das höchste
der Gefühle sind nullterminierte Arrays von char oder wchar. Memory
Management? Nix da, das darf der arme C-Entwickler alles von Hand
machen -- und wenn er sich dabei mal vertut, egal ob es ein doppeltes
free() ist oder ein anderer Fehler -- führt das überaus regelmäßig zu
Abstürzen oder gar, noch schlimmer, zu bösen Sicherheitslücken.
> Es geht mir nicht darum zu sagen, C wäre besser als Python, sondern> darum, dass die Implikation, Python sei besser als C, genauso falsch> ist.
Niemand hat gesagt, Python sei besser als C. Diese Diskussion findet,
Pardon, ausschließlich in Deinem eigenen Kopf statt, und mit Deinem
eigenen Stohmann mußt Du leider selbst fechten.
Was cppbert gesagt hat, ist, daß Python hinsichtlich der Features C
jederzeit spielend schlägt, und ganz genau so ist das auch, wie ich
oben ja schon erklärt habe. C ist eben eine relativ alte und ziemlich
maschinennahe Sprache der dritten Generation mit einer relativ dünnen
Abstraktionsschicht zur ausführenden Hardware, während Python von
vorneherein als General-Purpose-Programmiersprache entworfen wurde und
schon viele Elemente einer Sprache der vierten Generation enthält.
Schau einfach mal kurz auf die Dokumentation der Standardbibliotheken
von Python unter https://docs.python.org/3/library/index.html -- und
dann frag' Dich mal bitte selbst, welche Features davon C mit seinen
Standardbibliotheken von Haus aus beherrscht. Dasselbe gilt noch viel
mehr, wenn Du die Standardbibliotheken außen vor läßt...
> Abgesehen davon, klar haben beide Familien ihre spezifischen Vor- und> Nachteile. Nur deshalb ist es noch lange kein Bullshit, mal von einer> Seite welche hervorzuheben, wenn es nötig wird. Wenn man alle Vor und> Nachteile von Sprachen einfach als irrelevanter Bullshit abtut, wird es> doch absolut Sinnfrei, über diese Argumentieren zu wollen.
Ist es denn -- für irgendeine beliebige Definition dieses Wortes --
"nötig"? Ich glaube nicht. Und sogar Dir fällt doch offenbar nichts
Besseres dazu ein, als Dich ausgerechnet auf etwas zu kaprizieren, das
weder ein Alleinstellungsmerkmal von C ist und darüber hinaus auch nur
ein Unterschied einerseits im Übersetzungs- und Ausführungsmodell der
verschiedenen Sprachfamilien und andererseits ein daran eng gebundener
Unterschied in der Typisierung dieser Familien ist. Und zweitens fällt
Dir dazu etwas ein, das eine beliebte Quelle von Laufzeitfehlern wie
Abstürzen und gefährlichen Sicherheitslücken ist... Dein Ernst? Sorry,
das ist nicht der hochkompetente Daniel, den ich kenne. Oder bist Du
nicht jener Daniel und hast seinen Account gekapert?
Abschließend möchte ich noch anmerken, daß es dazu noch einen weiteren
Aspekt gibt. Ja, richtig, Python und seine Referenzimplementierung
(die in C geschrieben ist) sind stark, aber dynamisch typisiert. Aber
der (in Python entwickelte) Interpreter PyPy verwendet intern ein
Subset von Python namens RPython, das statisch typisiert wird und von
einem JIT-Compiler so effizient ausgeführt wird, das es in speziellen
Fällen [1] sogar schneller sein kann als C.
Solche speziellen Fälle treten in der Realität übrigens gar nicht so
selten auf, weil C selbst so einen überschaubaren Funktionsumfang hat
und deswegen häufig Funktionen aus dynamischen geladenen Bibliotheken
benutzen muß. Die kann der Optimierer des Compilers aber leider nicht
inlinen, sondern muß relativ aufwändige Operationen betreiben, um den
Code aus der Bibliothek auszuführen.
[1]
https://morepypy.blogspot.com/2011/02/pypy-faster-than-c-on-carefully-crafted.html
Joachim D. schrieb:> Da könnte man auch argumentieren; Phyton ist in C geschrieben,> dann nehme ich gleich das Original ;)
Das stimmt. Aber wenn man diese Argumentation weiterdenkt, dann braucht
man doch auch kein C. C wird ohnehin in Assembler übersetzt, also warum
nicht gleich in Assembler entwickeln? Und ach, wozu eigentlich
Assembler, das wird doch nur in Maschinencode übersetzt, da kann man
doch gleich das Original... naja, viel Erfolg, YMMV! ;-)
> Ich denke, das wird sich ergänzen. In C zB eine Mail senden> gibt locker 80 Zeilen Code, in Phyton sind es 2. Natürlich nur> einmal Arbeit (kann man ja wiederverwenden).
Richtig, Python hat wie andere interpretierte Skriptsprachen eine
deutlich höhere Abstraktionsebene. Deswegen muß man (unter anderem)
keine Typen für die Variablen deklarieren und muß sich auch um das
Speichermanagement nur sehr selten Gedanken machen, darum kümmert sich
Python. Aber diese höhere Abstraktionsebene führt zu enormen Vorteilen
hinsichtlich der Entwicklungszeit -- nicht nur, weil in Python dasselbe
Ergebnis mit wesentlich weniger Code erzielt werden kann.
Für maximale Performanz, etwa bei aufwändigen Berechnungen von
Massendaten oder in einem Betriebssystemkernel ist C daher zwar deutlich
aufwändiger zu entwickeln, in seiner Performanz jedoch ungeschlagen. Und
ja, auch erfahrene Assemblerentwickler können mit den Fähigkeiten
moderner Optimizer in C nur selten mithalten.
Bei schätzungsweise deutlich über 90% der Programme, die geschrieben
werden, spielt die Performanz aber eine vollkommen untergeordnete Rolle.
Meist, weil das Programm ohnehin den Großteil seiner Laufzeit auf
Eingaben wartet, entweder des Benutzers, von der Festplatte oder aus dem
Netzwerk. Wenn ich ohnehin schon eine Sekunde lang auf die zu
verarbeitenden Daten warten muß, spielt es auch keine große Rolle mehr,
ob mein Programm eine Tausendstel oder eine Hundertstel Sekunde zur
Verarbeitung dieser Daten braucht.
> Mal schnell 10 GB an Daten irgendwo einsortieren dürfte unter> C erheblich schneller gehen.
Ja, ganz sicher tut es das, aber auch da würde ein kluger Entwickler
vermutlich nicht C, sondern das viel komfortablere C++ nehmen. Das hat
nämlich in seiner Standard Template Library (STL) (sowie den
Boost-Bibliotheken) effiziente und ausgereifte Klassen und Funktionen
für solche Operationen.
Mir selbst ist sowas vor einigen Jahren begegnet, dabei ging es ums
Housekeeping einer Datenbank, in die täglich etwa 100.000 Schadensfälle
mit Betrugsbewertungen eingeliefert wurden. Da viele Schadensfälle
mehrfach eingeliefert wurden, jedoch lediglich die letzte und die
höchste Betrugsbewertung gebraucht wurde, wollte ich eine intelligente
Bereinigung der Datenbank um die nicht benötigten Fälle, um die
Explosion der Datenbank (PostgreSQL) zu vermeiden.
Zuerst habe ich mich mit SQL drangegeben; nach vier Tagen hatte ich dann
zwar ein korrektes Ergebnis, aber eine Laufzeit von einer Woche für die
tägliche Reinigung der Datenbank... es liegt auf der Hand, daß das keine
Lösung des Problems war. In Python dauerte die ganze Sache dann nurmehr
acht Stunden, das wäre zwar gegangen, erschien mir aber auch nicht sehr
erstrebenswert, zumal der Kunde hin und wieder fehlerhafte Daten
geliefert hat und die dann jeweils gelöscht und die korrekten Daten
neuprozessiert werden mußten.
Schließlich habe ich mich dann mit C++ daran gegeben, damit lag die
Laufzeit des Programms bei nurmehr etwa einer halben Stunde. Kompilierte
und maschinennahe Sprachen haben also sowohl ihre Berechtigung als auch
ihre Vorteile, der Punkt bleibt allerdings: in den meisten Fällen
spielen diese keine echte Rolle.
> SQLite geht auch unter Python.
Ja, natürlich, und mit einem OR-Mapper wie SQLObject oder SQLAlchemy, um
einige der beliebtesten zu nennen, geht das häufig sogar viel einfacher
und zudem unabhängig von der jeweiligen Datenbank. Mit so einem
OR-Mapper kannst Du nämlich jederzeit von SQLite auf eine andere
unterstützte Datenbank wechseln, für SQLObjekt zum Beispiel PostgreSQL,
MySQL, MaxDB oder Sybase -- und alles, was Du dazu tun mußt, ist, den
Connectionstring in der Konfiguration anzupassen.
Python selbst bietet mit PDO übrigens bereits einen Standard für den
einfachen Zugriff auf verschiedene Datenbanken an. Das funktioniert
prima, wenn man keine spezifischen Features der betreffenden Datenbank
braucht. Andererseits kann das insbesondere bei großen Datenmengen und /
oder komplexen Queries performanter sein als ein OR-Mapper. Da die
OR-Mapper aber intern alle einen PDO-kompatiblen Treiber verwenden, an
dessen Datenbankhandle man mit einigen kleinen Verrenkungen immer
herankommen kann, läßt sich in solchen Fällen durchaus auch nativer
SQL-Code mit solchen OR-Mappern verwenden, allerdings nur unter Einbuße
der Unabhängigkeit von der jeweiligen Datenbankplattform.
> Die Sachen die ich kenne und brauche sind alle vorhanden, ich> muß sie nur finden ...
Die Dokumentation von Python unter https://docs.python.org/ bietet eine
sehr gute Übersicht über die Sprache in der Language Reference, über die
Standardbibliotheken in der Library Reference, und unter
https://pypi.org/ findest Du etliche Module aus Drittquellen. Wenn Du
solche Third-Party-Module benutzen möchtest, will ich Dir noch die
Installation und Benutzung von virtualenv [1] wärmstens nahelegen, damit
kannst Du vom Rest des Systems abgeschottete Python-Umgebungen anlegen
und benutzen, ohne etwas in Deine System- und Benutzerverzeichnisse zu
installieren. Und es ist damit auch möglich, die installierte Version
Deiner Third-Party-Module festzulegen, was hin und wieder durchaus
hilfreich sein kann... HTH! ;-)
[1] https://virtualenv.pypa.io/en/latest/
Hi Sheeva,
das ist alles korrekt und nachvollziehbar.
Ich bin aber mit zB dBASE IV ziemlich auf die Schnauze geflogen
weil das im Netzwerk nicht richtig funktioniert hatte (komplette
Netzwerksbstürze 1mal am Tag) und Ashton-Tate danach platt war.
Es war ein CAD-Postprozessor Calay auf Bestückautomaten und
Handbestückplätze für eine grüßere Bestücklinie. Das geht nicht.
Ich hatte mir damals geschworen nie mehr 3rd-Party einzusetzen.
Schreibe ich es selbst habe ich noch eine Chance ...
Über meinen Schatten bin ich dann mit Btrieve gesprungen, aber
auch erst nach brutalen Tests (volle Last Daten reinschreiben,
dann dem Server den Netzstecker ziehen, überlebt das die DB
ist das System ok). Btrieve ist genial aber zu teuer mittlerweile.
Bei SQLite habe ich den Vorteil: keine Administration. Ich
muß nicht den armen Admin dauernd mit Updates belästigen, es
läuft einfach. Wir müßten sonst in der Firma 2 Leute dafür
einstellen die es im Moment nicht wirklich gibt.
--
Die Pythondoku etc. wühle ich gerade durch. Ich muß ein
Gefühl für die Sprache entwickeln und das dauert halt.
Der Sprachvergleich ist irgendwie auch obsolet: Ich kann
definitiv in C alles machen, in Python kann ich halt Module,
die andere schon gebaut haben, auch verwenden und Arbeit
sparen. In Assembler geht das natürlich auch, hat erheblich
mehr Aufwand ;)
Grüße Joe (mit ausdrücklichem Dank für die interessanten
und ausführlichen Posts)
DPA schrieb:> Python würde ich aber nicht als stark Typisiert betrachten.
Tja, zum Glück ist es völlig irrelevant, was du würdest und was nicht.
Natürlich ist es stark typisiert, sonst würde '3' + 7 keine Exception
werfen.
Ok, ich habe eventuell stark typisiert mit statisch typisiert
verwechselt. Kann mal passieren.
Wie dem auch sei, betrachten wir mal den Typ von X hier:
1
deff(x):
2
return3*x
Genau, zum jetzigen Zeitpunkt noch nicht bekannt. Das Problem ist halt,
Metadaten nützen nur etwas, wenn sie da sind, und auch verwendet werden.
Klar, man könnte einen typ angeben, aber man muss nicht. Bei C hat
man schon vor der Ausführung mehr Informationen über das Programm zur
verfügung, als bei python. Klar, es gibt Sprachen (z.B. Rust), die dass
noch viel weiter treiben. Klar, man kann in begrenztem Rahmen in python
vor der Ausführung die Typen prüfen, die bekannt sind. Aber ohne das
Programm auszuführen, kann man trotzdem viel weniger aussagen über ein
Python Programm machen, als über ein C programm. Python ist halt trotz
allem nicht statisch typisiert, und das ist und bleibt ein gutes
Argument für C. (Dynamische typisierung kann natürlich auch ein Vorteil
sein, aber den Blickwinkel haben wir ja schon.)
Sheeva P. schrieb:> Echt jetzt, Du willst mir sizeof() & Co als Reflexion bzw. Introspektion> verkaufen? Das ist hoffentlich nicht Dein Ernst.
Vielleicht nicht im engeren Sinne, aber im Grunde geht es bei all dem
Zeugs doch nur darum Metadaten über einen Programmteil zu ermitteln, und
im Programm zu nutzen.
Sheeva P. schrieb:> Weder die statische Typisierung, noch deren Prüfung in einem separaten> Kompilationsschritt sind also Kernfeatures von C, sondern einer ganzen> Sprachfamilie,
Klar gibt es viele Sprachen mit den Eigenschaften, dass ändert nichts
daran, dass C diese auch hat.
> DPA schrieb:>> Sheeva P. schrieb:>>> DPA schrieb:>>>> cppbert schrieb:>>>>> in Features schlägt Python C immer>>>>>>>> Nein. Es gibt viele Features, die nur C hat. Das fängt unter anderem mit>>>> der statischen typisierung an, und geht mit allen Konstrukten weiter,>>>> die damit möglich werden.>> Welche "Konstrukte" sollten das denn bitte sein? In C++ hätte ich ja> noch verstanden, wenn es im die Überladung von Methoden und Funktionen> geht, aber in C? Und von welchen anderen "Features" redest Du?
Denke z.B. an all die Dinge, die man in einen C header packen kann.
Diese "Interfaces", vor der Ausführung formal festgelegte Garantien
zwischen Programmteilen, und all das, was man damit machen kann.
> Und dann kommt auch noch erschwerend hinzu, daß C dank seines Typs> void leider gar nicht so typsicher ist, wie Du es darstellst.
Das ist ber kein Problem, denn mit void kann man nichts tun. Man kann
void nicht addieren, dereferenzieren, definieren, initialisieren, etc.
Man kann einen Pointer darauf haben, aber um etwas sinvolles damit
anfangen zu können, muss man es erst in einen anderen Typ casten. Und
dann hat man den Typ ja sowieso wieder explizit, schon vor der
Ausfürung, an der Stelle.
> Methoden? Membervariablen? In C?
Ja, so bezeichne ich meine Funktionspointer und Variablen in meinen
structs. Man versteht doch, was gemeint ist, das ist das Wichtige.
> Multithreading? Fehlanzeige, dazu braucht> es die externe pthread-Bibliothek.
C11 hat threads.h und stdatomics.h
>> Es geht mir nicht darum zu sagen, C wäre besser als Python, sondern>> darum, dass die Implikation, Python sei besser als C, genauso falsch>> ist.>> Niemand hat gesagt, Python sei besser als C.
Deshalb sag ich ja, Implikation. Es reicht, dass der Eindruck entsteht.
>> Abgesehen davon, klar haben beide Familien ihre spezifischen Vor- und>> Nachteile. Nur deshalb ist es noch lange kein Bullshit, mal von einer>> Seite welche hervorzuheben, wenn es nötig wird. Wenn man alle Vor und>> Nachteile von Sprachen einfach als irrelevanter Bullshit abtut, wird es>> doch absolut Sinnfrei, über diese Argumentieren zu wollen.>> Ist es denn -- für irgendeine beliebige Definition dieses Wortes --> "nötig"? Ich glaube nicht. Und sogar Dir fällt doch offenbar nichts> Besseres dazu ein, als Dich ausgerechnet auf etwas zu kaprizieren, das> weder ein Alleinstellungsmerkmal von C ist
Muss es ja auch nicht.
> und darüber hinaus auch nur ein Unterschied einerseits im Übersetzungs- und
Ausführungsmodell der
Man könnte sicher auch interpreter/script sprachen statisch typisieren.
> verschiedenen Sprachfamilien und andererseits ein daran eng gebundener> Unterschied in der Typisierung dieser Familien ist. Und zweitens fällt> Dir dazu etwas ein, das eine beliebte Quelle von Laufzeitfehlern wie> Abstürzen und gefährlichen Sicherheitslücken ist...
Es ist nunmal halt leider der wichtigste Unterschied, daran kann ich
nichts ändern.
Joachim D. schrieb:> Ich bin aber mit zB dBASE IV ziemlich auf die Schnauze geflogen> weil das im Netzwerk nicht richtig funktioniert hatte (komplette> Netzwerksbstürze 1mal am Tag) und Ashton-Tate danach platt war.> Es war ein CAD-Postprozessor Calay auf Bestückautomaten und> Handbestückplätze für eine grüßere Bestücklinie. Das geht nicht.
Nein, das geht nicht, das sehe ich genauso. Aber wenn man eine dermaßen
wichtige Datenbank für seine Produktionslinie(n) braucht, gibt es
natürlich Konzepte, um Hochverfügbarkeit umzusetzen. Vor zehn, fünfzehn
Jahren wäre ich bei soetwas wohl bei PostgreSQL und seinen relativ
einfachen, redundanzbasierten Lösungen gelandet, heutzutage würde ich
allerdings eher auf etwas moderneres aus dem Umfeld des DC (Distributed
Computing) gehen -- je Lastprofilen und Softwareumgebung vielleicht
Redis, Elasticsearch, Aerospike, Cassandra, Hazelcast, ... oder
womöglich Hana.
> Ich hatte mir damals geschworen nie mehr 3rd-Party einzusetzen.> Schreibe ich es selbst habe ich noch eine Chance ...
Das Problem dabei ist, daß Deine Lebenszeit vermutlich ähnlich endlich
ist wie meine, und daß auch selbstentwickelte Komponenten meistens
Fehler haben -- die, insbesondere in Grenzfällen und
Hochlastsituationen, schwierig bis gar nicht zu testen sind. Schau Dir
mal die Tests für verteilte Datenbanken von Kyle Kingsbury auf
http://jepsen.io/ an, das gibt Dir einen (groben) Vorgeschmack.
(Nebenbei: wenn Dich Datenbanken und Datenhaltung interessiert, empfehle
ich eines der mit Abstand großartigsten Bücher, die ich in den letzten
Jahren gelesen habe: "Designing Data-Intensive Systems" von Martin
Kleppmann).
Mein Weg ist übrigens genau andersherum verlaufen. Früher war ich so
heiß auf das Entwickeln und häufig mißtrauisch gegenüber fertigen
Systemen, daß ich bei jedem Problem erstmal den Editor angeworfen habe.
Aber das führt letztlich nur zu einem wesentlich größeren Problem, das
in der Softwarewelt unter NIH bekannt ist, "Not invented here". Dabei
neigt der Entwickler dazu, immer nur sein gerade aktuelles Problem zu
lösen, muß seine Software über ihren gesamten Lebenszyklus pflegen und
warten, und bei neuen Anforderungen erweitern oder sogar neu
schreiben... Kostet einen Riesenhaufen Zeit und Geld, und häufig ist das
Ergebnis weder so funktional noch so stabil wie eine etablierte
Standardlösung.
Was Datenbanken angeht, gibt es für mich daher mittlerweile nur noch
eine, und das ist PostgreSQL. Klein, schnell, superstabil, hat
wesentlich mehr Funktionsumfang als jede andere mir bekannte Datenbank,
und läßt sich wunderbar erweitern -- auch mit Stored Procedures und
Triggerfunktionen in Python. Und, wie gesagt, für wirklich wichtige
Dinge gibt es neben mehreren klassischen HA-Methoden mittlerweile auch
eine echte verteilte Version namens PostgresXL. Aber ich würde
PostgreSQL niemals unter etwas anderem produktiv betreiben als unter
Linux oder einem *BSD, obwohl ich schon ein stabiles PostgreSQL unter
Windows mit > 1 TB Daten gesehen habe.
> Bei SQLite habe ich den Vorteil: keine Administration. Ich> muß nicht den armen Admin dauernd mit Updates belästigen, es> läuft einfach. Wir müßten sonst in der Firma 2 Leute dafür> einstellen die es im Moment nicht wirklich gibt.
Klar, aber produktiv und unter Hochlast mit hoher Concurrency... dafür
ist SQLite halt nicht ausgelegt. Als Spielzeug benutze ich das auch
gerne, aber sonst bin ich da überaus skeptisch. Trotzdem, besser als was
selbstgebasteltes ist das natürlich allemal, vor allem auf lange
Sicht... ;-)
> Die Pythondoku etc. wühle ich gerade durch. Ich muß ein> Gefühl für die Sprache entwickeln und das dauert halt.
Mach' Dir keinen Streß, das kommt schon noch. Als interessante Lektüre
zum Thema empfehle ich gerne noch einen Artikel von Eric S. Raymond,
Autor von fetchmail und "The Cathedral and The Bazaar":
https://www.linuxjournal.com/article/3882 -- viel Vergnügen mit seinen
Erfahrungen, die den meinen sehr ähneln. ;-)
> Der Sprachvergleich ist irgendwie auch obsolet: Ich kann> definitiv in C alles machen, in Python kann ich halt Module,> die andere schon gebaut haben, auch verwenden und Arbeit> sparen. In Assembler geht das natürlich auch, hat erheblich> mehr Aufwand ;)
Klar, da sind wir wieder bei dem Lebenszeit-Thema. Und mit der Zeit
wirst Du merken, daß Du mit Python wesentlich größere Projekte angehen
und in einer überschaubaren Zeit schaffen kannst, als das mit C möglich
ist. Wie beim Versenden von Email, wie Du oben ja schon angemerkt hast:
zwei Zeilen Python gegen achtzig Zeilen C, und wenn dann ein Kunde kommt
und diese HTML- und Plaintext-Mails mit Templating haben will, nimmst Du
eben Jinja2 als Templateengine und noch zwei Zeilen Python dazu... ;-)
DPA schrieb:> Ok, ich habe eventuell stark typisiert mit statisch typisiert> verwechselt. Kann mal passieren.
Kein Thema. ;-)
> Wie dem auch sei, betrachten wir mal den Typ von X hier:>
1
>deff(x):
2
>return3*x
3
>
>> Genau, zum jetzigen Zeitpunkt noch nicht bekannt. Das Problem ist halt,> Metadaten nützen nur etwas, wenn sie da sind, und auch verwendet werden.
Danke für dieses schöne Beispiel, bei dem ich gern bleiben möchte. In
Python mit seinem Duck Typing [1] kann x nämlich alles sein, das die
Methode __rmul__() hat: eine Zahl (int, float, complex, ...), ein String
(str -- siehe dazu den Sonderfall, den ich oben erwähnt habe), oder
irgendeine Klasse, selbstdefiniert oder aus einem externen Modul: alles
kein Problem, siehe dazu mein erweitertes Beispiel:
In C müßte ich, weil es wegen seiner Funktionssignaturen keine
Überladung kann, für jeden einzelnen Datentyp jeweils eine eigene
Funktion implementieren. Denn im Kern ist statische Typisierung ja eine,
wenngleich gewünschte, Beschränkung. Damit wird mein Code aber leider
auch größer und unübersichtlicher.
C++ löst das Problem elegant mit Templates:
1
template<typenameT>Tf(Tval){return3*val;}
In C++ analysiert der Compiler anhand der statischen Typinformationen,
was mein Code zur Laufzeit der Funktion f() an Datentypen übergibt, und
erzeugt jeweils eigene Funktionen dafür alle diese Fälle -- es wäre mal
spannend zu schauen, was er für beispielsweise std::any macht, aber dazu
bin ich gerade zu faul.
C dagegen kann keine Objektorientierung, kein Überladen von Funktionen
und / oder Operatoren, kein... genau. In C müßte ich für jeden Datentyp,
mit dem ich mein f() benutzen will, eine eigene Version von f()
schreiben -- natürlich mit einem eigenen Namen. Und C kennt viele
numerische Datentypen: chat, int, long, float und double, gerne auch mit
den Modifikatoren signed, unsigned, short und long. Schon eine tolle
Sache, diese Typsicherheit. Ich persönlich würde vielleicht sogar dazu
neigen, mir einen kleinen Python-Codegenerator dafür zu schreiben und
mich darauf zu verlassen, daß der Optimizer des Compilers die
ungenutzten Versionen wegoptimiert. ;-)
Aber, fragst Du, wie ist das denn mit der Typsicherheit in Python? Nun,
wie oben bereits erwähnt, existieren Type Hints und Programme, die diese
überprüfen. Aber natürlich gibt es auch eine "harte" Methode:
1
import numbers
2
3
def f(x):
4
if not isinstance(x, numbers.Number):
5
raise TypeError('%s is not a Number'%(str(x)))
6
return x * 3
Klar, die schlägt auch erst zur Laufzeit an... Aber, wie oben bereits
länglich und ausführlich erläutert, ist das eine Eigenschaft, die alle
interpretierten Sprachen gemeinsam haben und dem Konzept "interpretierte
Sprache" prinzipbedingt, um nicht zu sagen: zwangsläufig inhärent sind.
[1] “When I see a bird that walks like a duck and swims like a duck and
quacks like a duck, I call that bird a duck.”
> Klar, man könnte einen typ angeben, aber man muss nicht. Bei C hat> man schon vor der Ausführung mehr Informationen über das Programm zur> verfügung, als bei python. Klar, es gibt Sprachen (z.B. Rust), die dass> noch viel weiter treiben. Klar, man kann in begrenztem Rahmen in python> vor der Ausführung die Typen prüfen, die bekannt sind. Aber ohne das> Programm auszuführen, kann man trotzdem viel weniger aussagen über ein> Python Programm machen, als über ein C programm. Python ist halt trotz> allem nicht statisch typisiert, und das ist und bleibt ein gutes> Argument für C. (Dynamische typisierung kann natürlich auch ein Vorteil> sein, aber den Blickwinkel haben wir ja schon.)
Tut mir leid, aber ich sehe das immer noch nicht als Argument für C,
wenn ich mir diese oben von mir bereits ausgeführte Sache mit den
C++-Templates betrachte. Das kann C++ wesentlich besser, und deswegen
sehe ich, mit Ausnahme von Domänen mit großen Mengen vorhandenen Codes
wie der Kernelentwicklung, heute kein einziges Argument mehr für C --
jedoch einige für C++ und andere für Skriptsprachen.
Der wesentliche Kernpunkt bei der Entscheidung zwischen einer
kompilierten oder einer interpretierten Sprache ist aber eine
Ressourcenentscheidung. Was ist Dir wichtiger, Entwicklungszeit oder
Rechenzeit? Und nein, ich meine nicht Laufzeit, denn die meisten
Programme vertrödeln heute den Großteil ihrer Laufzeit mit dem Warten
auf Input: vom Benutzer, vom Netzwerk, oder irgendeiner Persistierung.
> Sheeva P. schrieb:>> Echt jetzt, Du willst mir sizeof() & Co als Reflexion bzw. Introspektion>> verkaufen? Das ist hoffentlich nicht Dein Ernst.>> Vielleicht nicht im engeren Sinne, aber im Grunde geht es bei all dem> Zeugs doch nur darum Metadaten über einen Programmteil zu ermitteln, und> im Programm zu nutzen.
Ich bitte Dich, Daniel...
> Sheeva P. schrieb:>> Weder die statische Typisierung, noch deren Prüfung in einem separaten>> Kompilationsschritt sind also Kernfeatures von C, sondern einer ganzen>> Sprachfamilie,>> Klar gibt es viele Sprachen mit den Eigenschaften, dass ändert nichts> daran, dass C diese auch hat.
Aber genau das ist ja mein Punkt: es geht um verschiedene Konzepte.
>> DPA schrieb:>>>> DPA schrieb:>>>>> cppbert schrieb:>>>>>> in Features schlägt Python C immer>>>>>>>>>> Nein. Es gibt viele Features, die nur C hat. Das fängt unter anderem mit>>>>> der statischen typisierung an, und geht mit allen Konstrukten weiter,>>>>> die damit möglich werden.>>> Denke z.B. an all die Dinge, die man in einen C header packen kann.> Diese "Interfaces", vor der Ausführung formal festgelegte Garantien> zwischen Programmteilen, und all das, was man damit machen kann.
Das können C++ und andere auch und ist also nichts, das "nur C" kann --
und in C sind es ja auch leider nur mittelprächtige Funktionssignaturen.
>> Und dann kommt auch noch erschwerend hinzu, daß C dank seines Typs>> void leider gar nicht so typsicher ist, wie Du es darstellst.>> Das ist ber kein Problem, denn mit void kann man nichts tun.
Ich habe schon ein paar Funktionen gesehen, die zur Laufzeit böse
explodiert sind, weil sie einen falsche void-Pointer erhalten haben...
>> Methoden? Membervariablen? In C?>> Ja, so bezeichne ich meine Funktionspointer und Variablen in meinen> structs. Man versteht doch, was gemeint ist, das ist das Wichtige.
Nenn' mich vernagelt, aber es widerstrebt mir, objektorientierte
Fachausdrücke auf etwas anzuwenden, das nicht objektorientiert ist. Es
wäre sicherlich einfacher, mit Dir zu diskutieren, wenn Du davon
absähest, eindeutig definierte Fachausdrücke für davon unabhängige Dinge
zu mißbrauchen. ;-)
>> Multithreading? Fehlanzeige, dazu braucht>> es die externe pthread-Bibliothek.>> C11 hat threads.h und stdatomics.h
Ui, das wußte ich nicht. Dann gibt es bestimmt bald auch Multi- und
Asynchrones Processing, ich bin gespannt. ;-) Ist aber auch nur ein
Punkt von den vielen, die ich genannt habe, oder nicht?
>>> Es geht mir nicht darum zu sagen, C wäre besser als Python, sondern>>> darum, dass die Implikation, Python sei besser als C, genauso falsch>>> ist.>>>> Niemand hat gesagt, Python sei besser als C.>> Deshalb sag ich ja, Implikation. Es reicht, dass der Eindruck entsteht.
Das wurde aber auch nie impliziert -- es wurde ja lediglich gesagt: "in
Features schlägt Python C immer". Und das ist, egal wie Du es drehst und
wendest, schlicht und ergreifend eine Tatsache.
>> und darüber hinaus auch nur ein Unterschied einerseits im Übersetzungs- und> Ausführungsmodell der>> Man könnte sicher auch interpreter/script sprachen statisch typisieren.
Das tut aber niemand, und weißt Du, warum? Weil es Unfug ist!
Skriptsprachen haben ohnehin keinen separaten Kompilationsschritt, in
dem diese statische Typisierung überprüft werden kann. Man kann in
Skriptsprachen -- unabhängig von der konkreten Typisierung -- viel
schneller entwickeln, und zwei wesentliche Gründe dafür sind, daß auf
eine manuelle Ressourcenverwaltung und auch auf eine statische
Typisierung (weitestgehend) verzichtet wird.
Genau dieser Verzicht führt aber dazu, daß die Produktivität des
Entwicklers in einer interpretierten Sprache viel höher ist als in einer
kompilierten. Deswegen müssen wir im Kern über Ressourcen reden:
Computerressourcen versus menschliche Arbeitszeit. Du fügst nun noch
einen weiteren Punkt hinzu, die Fehlerbehandlung.
Ehrlich gesagt -- und in Kenntnis verschiedener Studien zu diesem Thema
-- glaube ich nicht, daß Du Dich auf diese Diskussion einlassen
möchtest. Entwickler sind wesentlich teurer als Computer, und deswegen
haben die interpretierten Sprachen in der Breite schon längst gewonnen,
außer in bestimmten Domänen: Hochperformanz und Betriebssystemkerne.
Dort, wo es um schnelle Anpassungen und Veränderungen geht, insbesondere
im Webdevelopment, gibt es so gut wie gar nichts Kompiliertes mehr,
dort, wo es außerdem um Stabilität und Performanz geht, wird es für
Kompilierte langsam wirklich eng: die größte Bank der Welt,
Goldman-Sachs, beschäftigt etwa eintausend Python-Entwickler sicher
nicht aus Vergnügen. Die NASA auch nicht...
Wobei das ja auch nicht ganz richtig ist: Hochperformanz wird heute sehr
häufig in Python gemacht. Warum? Weil wir bekloppten Kids längst von
einzelnen Rechnern weg sind und mit Clustern aus Commodity-Rechnern
arbeiten. Okay, die Klügeren von uns jedenfalls. Was meinst Du wohl,
warum es für Python solche coolen Erweiterungen wie numpy, scipy oder
Pandas gibt, und warum etliche Distributed-Computing-Frameworks
Schnittstellen für Python mitbringen? Genau.
Warum ist Python in der wissenschaftlichen Gemeinde so beliebt? Richtig:
weil die Leute dort sich lieber auf ihre Domäne, also ihre Wissenschaft
konzentrieren, als sich um Ressourcenverwaltung und Datentypisierung zu
kümmern. Daten fressen und kommunizieren, das ist deren Job. Gibt es was
wie Matplotlib oder Bokeh für C?
... an dieser Stelle könnte ich vermutlich noch zehntausend Zeilen
weitermachen, aber ich möchte Dir nicht auf die Füße treten -- und auch
zu den vielen anderen C-Freunden in diesem Forum nicht gemein sein.
Alles gut, Daniel?