Re: [Python-de] strings zusammensetzen.

Am 30.08.2017 um 21:24 schrieb Peter Otten:
der wegen des Lernaufwandes und Manual Suchens lieber os.system("rm "+dateiname) als os.unlink(dateiname) verwendet.
os.unlink() dürfte aber portabler sein und auch mit Leerzeichen und anderen speziellen Zeichen in dateiname zurechtkommen. Wer weiss, was die Shell so treibt.
Bei Risisko halt: os.system('rm "'+dateiname+'"')
Das nützt nix. Sobald Dritte den Dateinamen bestimmen können, bekommst du Probleme:
$ cat demo.py import glob import os
for filename in os.listdir(): if not filename.endswith(".py"): print("removing", repr(filename)) os.system("rm '" + filename + "'") $ touch foo'\ -f;echo\ 'oops $ python3 demo.py removing "foo' -f;echo 'oops" oops $
ok.
Allerdings fällt mir bei der Gelegenheit ein, was ist, wenn der Dateiname ein bytestring ist, der sich nicht nach utf konvertieren lässt? In C ist ja als Dateiname alles außer '/' und '\0' erlaubt.
Hermann der bisher bytestring lediglich zum Vergleich von Dateiinhalten verwendet hat.

Hermann Riemann wrote:
Allerdings fällt mir bei der Gelegenheit ein, was ist, wenn der Dateiname ein bytestring ist, der sich nicht nach utf konvertieren lässt? In C ist ja als Dateiname alles außer '/' und '\0' erlaubt.
Unter Linux kein Problem:
import os ord("/")
47
filename = bytes(c for c in range(1, 256) if c != 47) filename
b'\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
os.path.exists(filename)
False
with open(filename, "w") as f: f.write("yadda\n")
... 6
os.path.exists(filename)
True
os.listdir()
['\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\udc80\udc81\udc82\udc83\udc84\udc85\udc86\udc87\udc88\udc89\udc8a\udc8b\udc8c\udc8d\udc8e\udc8f\udc90\udc91\udc92\udc93\udc94\udc95\udc96\udc97\udc98\udc99\udc9a\udc9b\udc9c\udc9d\udc9e\udc9f\udca0\udca1\udca2\udca3\udca4\udca5\udca6\udca7\udca8\udca9\udcaa\udcab\udcac\udcad\udcae\udcaf\udcb0\udcb1\udcb2\udcb3\udcb4\udcb5\udcb6\udcb7\udcb8\udcb9\udcba\udcbb\udcbc\udcbd\udcbe\udcbf\udcc0\udcc1\udcc2\udcc3\udcc4\udcc5\udcc6\udcc7\udcc8\udcc9\udcca\udccb\udccc\udccd\udcce\udccf\udcd0\udcd1\udcd2\udcd3\udcd4\udcd5\udcd6\udcd7\udcd8\udcd9\udcda\udcdb\udcdc\udcdd\udcde\udcdf\udce0\udce1\udce2\udce3\udce4\udce5\udce6\udce7\udce8\udce9\udcea\udceb\udcec\udced\udcee\udcef\udcf0\udcf1\udcf2\udcf3\udcf4\udcf5\udcf6\udcf7\udcf8\udcf9\udcfa\udcfb\udcfc\udcfd\udcfe\udcff']
Hier sieht man, was mit nicht dekodierbaren Bytes geschieht -- Python verwendet den surrogate-escape error handler:
b"\xf1\xf2\xf3".decode("utf-8", "surrogateescape")
'\udcf1\udcf2\udcf3'
Die Shell kann da nicht mithalten:
[2]+ Angehalten python3 $ ls ??????????????????????????????? !"#$%&'()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? $ fg python3
os.remove(filename) os.listdir()
[]
Unter Windows sind die Regeln wohl etwas komplexer.

Am 31.08.2017 um 14:40 schrieb Hermann Riemann:
[...]
In C ist ja als Dateiname alles außer '/' und '\0' erlaubt.
C definiert zu dem, was in einem Dateinamen erlaubt ist gar nichts.
Thomas

Am 31.08.2017 um 19:11 schrieb Thomas Orgelmacher:
In C ist ja als Dateiname alles außer '/' und '\0' erlaubt.
C definiert zu dem, was in einem Dateinamen erlaubt ist gar nichts.
ANSI C und ältere Unix (Linux) waren "verheiratet".
Sprachen wie Ada, Java und Python bauen ihre eigene Betriebssystem Umgebungen auf. Wobei nach meiner Erfahrung fast alles Konflikte mit utf-8 hat(te). ( Erwartete 64 bit Konflikte habe ich bisher kaum bemerkt.)
Wobei manchmal seltsame Dinge entstehen wie: https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-f...
( dank SuSE bin ich ich praktisch an 3.4 (bei SuSE 42.3 immer noch) gebunden.)
Bei Python2 war pygame SDL gebunden. Ob irgendwann bei Python3 und pygame (pygame2?) SDL2 aktiv wird, habe ich nicht herausgefunden. ( pygame habe ich bisher nicht benutzt. SDL* in C bleibt wegen schneller Pixelmanipulation. Für einfache Grafiken könnte pygame interessant werden.)
Ach ja. Die aus FORTRAN Zeiten stammende %s Darstellung ist nach einer Messung in dieser Ecke schneller als {} und nach meinem Eindruck auch besser lesbar; aber ich vermute, dass bei Python 4? %s vielleicht nicht mehr unterstützt wird.
Hermann gedanklich schon an ein Umsetzer Python3 Program ( mit tokenize ) denkend, welche z.B. os.system("rm ",filename) in os.unlink(filename) umwandelt.

Am 01.09.2017 um 09:12 schrieb Hermann Riemann:
Am 31.08.2017 um 19:11 schrieb Thomas Orgelmacher:
In C ist ja als Dateiname alles außer '/' und '\0' erlaubt.
C definiert zu dem, was in einem Dateinamen erlaubt ist gar nichts.
ANSI C und ältere Unix (Linux) waren "verheiratet".
Bei älteren Unices war das wohl eher K&R. ANSI C gibt's AFAIK erst seit 1989. Und Linux und Unix haben auf der Ebene generell nicht viel gemein.
Und "verheiratet"? Die sind in C geschrieben, ja. Und?
Sprachen wie Ada, Java und Python bauen ihre eigene Betriebssystem Umgebungen auf.
Nein. Wie kommst Du darauf?
Ada definiert zwar ziemlich viel auf Sprachebene, aber AFAIK gehören Pfade nicht dazu. Python hat pathlib. Aber von allein passiert da gar nichts. Ebenso bei Java.
[...]
( dank SuSE bin ich ich praktisch an 3.4 (bei SuSE 42.3 immer noch) gebunden.)
Python ist geradezu trivial zu kompilieren. Man kann da eigentlich nicht viel falsch machen. Man kann natürlich auch auf den Distributor warten.
[...]> Ach ja.
Die aus FORTRAN Zeiten stammende %s Darstellung
Und ich hätte schwören können, dass 'A' FORTRANs Formatierungsbezeichner für Strings ist. Naja, ist lange her...
ist nach einer Messung in dieser Ecke schneller als {} und nach meinem Eindruck auch besser lesbar; aber ich vermute, dass bei Python 4? %s vielleicht nicht mehr unterstützt wird.
Und wo kommt das her? Laut 3.7.0a0 ist der Operator noch nicht einmal "deprecated".
Gruß, Thomas

Thomas Orgelmacher schrieb am 01.09.2017 um 21:06:
Am 01.09.2017 um 09:12 schrieb Hermann Riemann:
aber ich vermute, dass bei Python 4? %s vielleicht nicht mehr unterstützt wird.
Und wo kommt das her? Laut 3.7.0a0 ist der Operator noch nicht einmal "deprecated".
Python 4.0 wird wohl erst nach Python 3.9 erscheinen, was auch noch runde vier Jahre hin ist, also so in 5-6 Jahren. Und Guido hat mehrfach geäußert, dass Python 4 im Gegensatz zu Python 3 keine großen Kompatibilitätsbrüche mit sich bringen soll.
Für letztere gibt es ohnehin die normalen Auslaufzeiten, also eine "PendingDeprecationWarning" mit einem neuen Release, z.B. 3.7, dann eine "DeprecationWarning" mit dem nächsten, z.B. 3.8, dann die Entfernung mit dem darauf folgenden. "%"-Formatierung könnte also frühestens mit 3.9 entfernt werden. Ist aber unwahrscheinlich, weil der Bruch einfach zu groß wäre. Die Konvertierung in ".format()" oder f-Strings lässt sich nämlich auch nicht gut automatisieren, weil ja nicht immer über Literale formatiert wird, und dahinter auch nicht immer erkennbare Tupel stehen. Also wage ich mal zu orakeln, dass die "%"-Formatierung uns noch ein ganzes Weilchen länger als die nächsten 5 Jahre erhalten bleiben wird. Trotz der hübschen f-Strings.
Aber ich möchte auch orakeln, dass es zumindest Tools geben wird, die Literale zur %-Formatierung und ".format()" in f-Strings konvertieren können werden. Irgendwann schreibt das mal wer, vermutlich als 2to3-Fixer. Könnte einige Leute glücklich machen.
Stefan

On Fri, 1 Sep 2017 21:06:11 +0200 Thomas Orgelmacher trash@odbs.org wrote:
[...]
( dank SuSE bin ich ich praktisch an 3.4 (bei SuSE 42.3 immer noch) gebunden.)
Python ist geradezu trivial zu kompilieren. Man kann da eigentlich nicht viel falsch machen. Man kann natürlich auch auf den Distributor warten.
Ich kann da pyenv und pyenv-installer (https://github.com/pyenv/pyenv-installer) empfehlen. Da muss man sich weder mit dem System-Python, noch dem Distributor rum ärgern.
- Arnold
participants (5)
-
Arnold Krille
-
Hermann Riemann
-
Peter Otten
-
Stefan Behnel
-
Thomas Orgelmacher