Python-Unterstützung bei londonlaw

Du hast eine Idee für ein Projekt?
Antworten
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo Leute,

da ich zur Zeit eine Weiterbildung zum Python-Programmierer mache und das Spiel londonlaw (https://wiki.ubuntuusers.de/Spiele/Ubun ... London-Law) eine Adaption von Scotland Yard (https://en.wikipedia.org/wiki/Scotland_ ... oard_game)) gerne mit meiner Tochter spiele, dachte ich es wäre eine gute Idee es auf python3 zu portieren. Leider bekomme ich bei der Weiterbildung nicht die Unterstützung, die ich mir erhofft hatte. Und da es ja sicherlich professionelle Python-Programmierer hier gibt, dachte ich, ich frage mal hier an. Ich habe bereits einen Folk angelegt: https://github.com/horald/londonlaw
Mir geht es zur Zeit vorrangig auch nur um den guiclient. Den Server kann ich auf einer anderen Maschine laufen lassen, wo noch python2 installiert ist. Nur Ubuntu 20.04. unterstützt python2 nicht mehr, daher wollte ich es eben für python3 anpassen. Die Anmeldemaske kommt auch bereits hoch, aber die Verbindung klappt noch nicht und als ungeübter Pythonprogrammierer habe ich leider den Fehler noch nicht gefunden. Danke für Eure Unterstützung.

Viele Grüße
Horst Meyer
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du eine Fehlermeldung zeigst, dann kann man sich das mal anschauen.
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Danke für die Rückmeldung. Das Programm ist mit einem logging ausgestattet. Die logging-Datei findest Du auch in meinem Folk: https://github.com/horald/londonlaw/blo ... client.log
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nur eine kurze Anmerkung: Folk ist Volk. Fork ist eine Abzweigung (oder Gabel). Das ist was du mit github angelegt hast.

Und log files würde ich nicht in git packen. Da gehören solche flüchtigen Daten nicht hin. Wenn du den Umgang mit den Tools üben willst (was ja sehr sinnvoll ist), dann benutz für so etwas zb einen Issue, dafür sind die ja gedacht. Oder einen github gist.

Zu deinem Fehler: Python 3 hat massiv den Umgang mit strings und Byte-Sequenzen verändert. Dadurch läuft viel Code in Python 3 nicht mehr (zu recht), der in 2 noch durchgewunken wurde.

Den Unterschied zu verinnerlichen (also was Strings und was Bytes sind), ist fundamental. Und hier zb https://portingguide.readthedocs.io/en/ ... rings.html findest du einen porting guide, der das berührt. Es findet sich sicherlich auch noch diverses anderes.

Aus Erfahrung will ich das nochmal betonen: es ist wirklich wirklich wichtig zu verstehen, was ein encoding ist, und wie sich das zu “rohen” Bytes und Strings verhält. Da eine Weile zu investieren wird dir viel Ärger in der Zukunft ersparen.
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo __deets___,

erstmal Danke für Deine ausführliche Antwort.
Nur eine kurze Anmerkung: Folk ist Volk. Fork ist eine Abzweigung (oder Gabel). Das ist was du mit github angelegt hast.
Ja, sorry, das war ein Tippfehler...
Und log files würde ich nicht in git packen. Da gehören solche flüchtigen Daten nicht hin. Wenn du den Umgang mit den Tools üben willst (was ja sehr sinnvoll ist), dann benutz für so etwas zb einen Issue, dafür sind die ja gedacht. Oder einen github gist.
Ich habe die log-Files jetzt in .gitignore mit aufgenommen. Ich dachte Issues legt man manuell an, oder kann man dies auch mit python erzeugen? Und gist sagt mir nichts. Wo finde ich nähre Infos? Wenn möglich auf deutsch....
Den Unterschied zu verinnerlichen (also was Strings und was Bytes sind), ist fundamental. Und hier zb https://portingguide.readthedocs.io/en/ ... rings.html findest du einen porting guide, der das berührt. Es findet sich sicherlich auch noch diverses anderes.
Der Link ist ja ganz schön. Aber ich finde es besser wenn python2 und python3 direkt nebeneinander gelegt würden, dann würde ich es besser verstehen, z.B. wie folgt:

Code: Alles auswählen

#python2
print "Hallo Welt"
#python3
print("Hallo Welt")
Aus Erfahrung will ich das nochmal betonen: es ist wirklich wirklich wichtig zu verstehen, was ein encoding ist, und wie sich das zu “rohen” Bytes und Strings verhält. Da eine Weile zu investieren wird dir viel Ärger in der Zukunft ersparen.
Ja genau darum stelle ich es ja hier ins Forum, weil ich als Python-Anfänger nicht so schnell die Erfahrung erlangen kann und Python-Programmierer, die diese Erfahrung haben mir eben weiterhelfen sollen....
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@horald: In dem Repository sind ja schon ein paar Commits, die sind aber alle entweder ohne Beschreibung oder mit einer supergenerischen.

Da ist so einiges was nicht ins Repository gehört! Logdateien, Backupdateien die der Editor/die IDE anlegt, und *.pyc-Dateien in `__pycache__`-Verzeichnissen haben nichts im Repository zu suchen.

Die `.gitignore` könnte auch ein bisschen generischer sein. Dateinamen die mit "~" enden will man eigentlich nie im Repository haben, da muss man nicht alle möglichen Dateiendungen + "~" auflisten.

Private Notizen (doc/MyGermanQuestion/) würde ich auch nicht ins Repository packen.

Zeilen wie folgende in den Code zu schreiben macht wenig Sinn:

Code: Alles auswählen

print("Not yet ready for Python3!")
print("Achtung! GameRegistry.py Zl 82 geändert!")
Die Änderung die in der erwähnten Zeile gemacht wurde, einfach ein Attribut auskommentieren, dass ja sehr wahrscheinlich irgendwo gebraucht wird, ist auch nicht so eine tolle Idee. Es gibt kein `sets`-Modul mehr weil `set()` mittlerweile (auch schon unter Python 2) ein eingebauter Datentyp ist.

Wo ich gerade die Änderungen in dem Commit überfliege: Da wird deutlich mehr `list()` eingesetzt als nötig.

Der Autor hat tatsächlich Backticks statt `repr()` verwendet. Ich bin schon ziemlich lange bei Python dabei, das habe ich so ausser in der Dokumentation und bei Code-Golf noch nie in einem echten Programm gesehen. 😱

2to3.py über Code laufen lassen und direkt das Ergebnis ”unbesehen” ins Repository stecken ist IMHO keine gute Idee. Das erfordert ja noch Nachbearbeitung und wenn man da nicht *gleich* mindestens mal TODO-Kommentare an diese Stellen setzt, vergisst man am Ende irgend etwas und muss da mühsam durch normale Fehlersuche drauf kommen.

Allgemein zur Strategie: Das ist ein ziemlich grosser Brocken und so wie Du das angehst viel Arbeit/Zeit die vergeht wenn man sich von Problem zu Problem hangelt, ohne das man in dieser Zeit ein funktionierendes Programm hätte. Ich würde das anders angehen und erst einmal Python 2 installieren. Dann das ganze in ein venv stecken und die Abhängigkeiten installieren die vor 6 Jahren, als der Code vom Autor das letzte mal angefasst wurde, aktuell waren. Denn man möchte eigentlich nicht den Schritt von Python 2 nach 3 *und* wxPython 3 nach 4 *gleichzeitig* machen müssen. Und was immer sich in der Zeit in Twisted geändert haben mag. Man kämpt dann einfach an zu vielen Fronten gleichzeitig.

Dann würde ich keinen Extracode einbauen damit das auch uninstalliert läuft, weil man mit `pip` auch ”editierbar” installieren kann. Das heisst man installiert das zwar, aber die Dateien werden an Ort und Stelle gelassen und man kann das so installierte Package weiterhin an Ort und Stelle bearbeiten.

Wenn man die Python 2 Umgebung von vor 6 Jahren hat, kann man nacheinander die Bibliotheken auf den aktuellen Stand für Python 2 bringen.

Und dann den Code in eine Form die keine veralteten Konstrukte mehr verwendet und was Python 2 so bietet was einen möglichst nahe an Python 3 bringt. Also keine Backticks statt `repr()`, ``except`` mit ``as`` statt mit ``,``, `print()` als Funktion mit entsprechendem `__future__`-Import und so weiter. Von den `__future__`-Sachen würde ich persönlich die Finger von `unicode_literals` lassen, weil das mit manchen Python 2-APIs Probleme machen kann.

Einige Änderungen lassen sich durch Werkzeuge wie 2to3.py (teil)automatisieren. Die Fixes würde ich *einzeln* anwenden und committen. Also automatisiert alle ``print``-Anweisungen zu `print()`-Aufrufen (+ `__future__`-Import) ändern. Dann die Änderungen alle durchgehen und schauen ob man da eventuell manuell was verbessern kann. Und dann erst committen. Und dann das gleiche mit der ``except``/``as``-Syntax. Da will man beispielsweise schauen ob der Name nach dem ``as`` vielleicht *nach* dem ``except``-Block noch verwendet wird. In Python 2 geht das, in Python 3 aber nicht mehr. Solchen Code müsste man dann manuell anpassen.

Wenn das dann alles auf Python 2.7, neueste Bibliotheksversionen, fertig zum Sprung auf Python 3 ist, kann man sich überlegen ob man wirklich den harten Sprung will, oder vielleicht erst einmal Code der auf beiden Versionen läuft. Das `six`-Modul ist da hilfreich.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

In meinem Link stehen im entsprechenden Absatz sprichwörtlich zwei Print-Anweisungen nebeneinander, so wie du dir das wünschst... so weit her kann es also mit dem Studium der Quelle nicht gewesen sein.

Und wenn dir ein Begriff unbekannt ist, wirf ihn in eine Suchmaschine, und schau was bei rumkommt. Wenn das immer noch Fragen offen lässt, kannst du die hier gerne stellen. Aber ohne intensives Selbststudium wird aus dem Traum vom Programmierer nix.

Und die erfahrenen (oder einer, ich) Programmierer haben dir doch recht deutlich ein spezifisches Gebiet genannt, aus dem heraus dein Problem rührt. Was sonst erwartest du?
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo Leute,
ich habe mich nochmal mit dem Quellcode beschäftigt und versuche nun den Server ans Laufen zu bringen. Der Server scheint jetzt wohl auf eine Verbindung zu warten, aber wenn ich mich mit dem Client verbinden will, stürzt der Server immer hier ab:

Code: Alles auswählen

2021-01-31 17:20:12+0100 [-] Log opened.
2021-01-31 17:20:12+0100 [-] dbdir=/home/horald/prgentw/python/londonlaw3/londonlaw/server
2021-01-31 17:20:12+0100 [-] dbDir=/home/horald/prgentw/python/londonlaw3/londonlaw/server
2021-01-31 17:20:12+0100 [-] Purging games involving AI clients
2021-01-31 17:20:12+0100 [-] LLawServerFactory starting on 7921
2021-01-31 17:20:12+0100 [-] Starting factory <server.LLawServerFactory object at 0x7f4291a54430>
2021-01-31 17:27:02+0100 [-] line=#00000 protocol 2.0
2021-01-31 17:27:02+0100 [LLawServerProtocol,0,192.168.0.178] Unhandled Error
	Traceback (most recent call last):
	  File "/usr/lib/python3/dist-packages/twisted/python/log.py", line 103, in callWithLogger
	    return callWithContext({"system": lp}, func, *args, **kw)
	  File "/usr/lib/python3/dist-packages/twisted/python/log.py", line 86, in callWithContext
	    return context.call({ILogContext: newCtx}, func, *args, **kw)
	  File "/usr/lib/python3/dist-packages/twisted/python/context.py", line 122, in callWithContext
	    return self.currentContext().callWithContext(ctx, func, *args, **kw)
	  File "/usr/lib/python3/dist-packages/twisted/python/context.py", line 85, in callWithContext
	    return func(*args,**kw)
	--- <exception caught here> ---
	  File "/usr/lib/python3/dist-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
	    why = selectable.doRead()
	  File "/usr/lib/python3/dist-packages/twisted/internet/tcp.py", line 243, in doRead
	    return self._dataReceived(data)
	  File "/usr/lib/python3/dist-packages/twisted/internet/tcp.py", line 249, in _dataReceived
	    rval = self.protocol.dataReceived(data)
	  File "/usr/lib/python3/dist-packages/twisted/protocols/basic.py", line 454, in dataReceived
	    self.lineReceived(line)
	  File "/home/horald/prgentw/python/londonlaw3/londonlaw/server/Protocol.py", line 564, in lineReceived
	    tokens = shlex.split(line)
	  File "/usr/lib/python3.8/shlex.py", line 311, in split
	    return list(lex)
	  File "/usr/lib/python3.8/shlex.py", line 300, in __next__
	    token = self.get_token()
	  File "/usr/lib/python3.8/shlex.py", line 109, in get_token
	    raw = self.read_token()
	  File "/usr/lib/python3.8/shlex.py", line 140, in read_token
	    nextchar = self.instream.read(1)
	builtins.AttributeError: 'bytes' object has no attribute 'read'


Hat einer eine Idee woran das liegen kann. Der Befehl shlex.split(line) ist doch richtig, oder? Danke
Viele Grüße
Horst
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@horald: Zwischen Python 2 und Python 3 hat sich das Verhalten von Zeichenketten fundamental geändert. Das könnte möglicherweise das Problem sein. Mehr kann man ohne Quellcode nicht sagen, außer das was du sowieso da lesen kannst: Bytes haben keine .read()-Methode:

Code: Alles auswählen

>>> x = b"test"
>>> type(x)
<class 'bytes'>
>>> bytes.read(1)
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    bytes.read(1)
AttributeError: type object 'bytes' has no attribute 'read'
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dast habe ich ja auch schon in meinem ersten Post erwaehnt. Aber scheint nicht so recht auf fruchtbaren Boden zu fallen.
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo sparrow,

danke für den Tipp, dass hat mir schon mal weitergeholfen. Jetzt bekomme ich im Protokoll immer folgenden Meldung:

Code: Alles auswählen

2021-01-31 18:14:59+0100 [-] Log opened.
2021-01-31 18:14:59+0100 [-] dbdir=/home/horald/prgentw/python/londonlaw3/londonlaw/server
2021-01-31 18:14:59+0100 [-] Purging games involving AI clients
2021-01-31 18:14:59+0100 [-] LLawServerFactory starting on 7921
2021-01-31 18:14:59+0100 [-] Starting factory <server.LLawServerFactory object at 0x7f3fab2d5c40>
2021-01-31 18:15:20+0100 [-] line=#00000 protocol 2.0
2021-01-31 18:15:20+0100 [-] b'Unrecognized protocol string.'
Ich verstehe allerdings nicht so ganz warum er den protocol string nicht erkennt. Da der Client auf einer anderen Maschine im Original läuft, sollte er auch den richtigen string abschlicken. Nur der Server kennt ihn nicht, nur wo ist der Fehler? Der Source-Code steht übrigens hier: https://github.com/horald/londonlaw

Viele Grüße
Horst
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und zum 3ten mal:

Code: Alles auswählen

>>> print(b'hallo'=='hallo')
False
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo zusammen,

es ist schon erstaunlich wieviel Unterstützung man in Pandemiezeiten bekommt!? In meinem github-Account, Moment..., ich zähle mal: Null Teilnehmer gemeldet! Wahnsinn. Und dann bekommt man so hilfreich Kommentare und Besserwisser, äh, Verbesserungsvorschläge, denn b'hallo'=='hallo' ist gar nicht gleich, oh. Da wäre ich niemals im Leben drauf gekommen. Vor allen Dingen ist mir gar nicht aufgefallen, wo dies im Quellcode steht? Habe ich wahrscheinlch übersehen. Welche Zeile war das nochmal? Da muß ich mich ja dreimal bedanken: wie nett, wie nett, wie nett. War nett nicht der Bruder von ... Ach, egal. Ihr wißt schon wie ich es meine. Dann mache ich es halt wie Münchhausen und ziehe ich mich am eigenen Schopf aus dem Programmiersumpf, der hat das ja auch geschafft, oder?

Viele Grüße
Horst Meyer
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@horald: Das war halt *noch mal* ein praktischer Hinweis darauf, dass sich in Python 3 das Verhalten von Byteketten und echten Zeichenketten drastisch geändert hat, denn in Python 2 sieht das so aus:

Code: Alles auswählen

$ python
Python 2.7.17 (default, Sep 30 2020, 13:38:04) 
[GCC 7.5.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> b"hallo" == u"hallo"
True
>>>
Und das kommt halt doch in dem Code vor. Nein, natürlich nicht so vereinfacht und offensichtlich das da eine literale Bytekette mit einer literalen Zeichenkette verglichen wird, aber es werden halt Bytes mit Zeichenketten verglichen. Und das ist in Python 2 in bestimmten Fällen automagisch möglich, in Python 3 aber Äpfel und Birnen und immer False, auch in den Fällen wo das in Python 2 noch True war.

Man muss für so eine Portierung den gesamten Code durchgehen und überall schauen ob ”Zeichenketten” nun tatsächlich Zeichenketten oder Bytes sind und den Code entsprechend anpassen. Das ist keine einfache Änderung wie ``print something`` zu ``print(something)`` oder ``except Exception, error:`` zu ``except Exception as error:`` die man automatisieren könnte. Da kann letztlich kein Programm bei helfen.

Ein erster Schritt könnte sein die literalen ”Zeichenketten” durchzugehen und konsequent als Bytekette (b"something") oder Zeichenkette (u"something") zu markieren. Aber das ändert wie oben gesehen leider die Semantik in Python 2 noch nicht, und es kann natürlich auch problematische Stellen geben bei denen gar keine literalen Werte involviert sind. Oder man bindet für den Übergang das `future`-Paket ein und markiert die Byteketten nicht nur mit dem ``b`` sondern verpackt die in `future.builtins.bytes`:

Code: Alles auswählen

>>> future.builtins.bytes("hallo") == u"hallo"
False
Das Problem ist hier natürlich auch wieder, dass man das auch mit allen nicht-literalen Werten machen muss die in Python keine Zeichenketten sondern Bytes sind. Man kommt nicht darum herum das gesamte Programm aufmerksam durchzugehen und zu schauen was Bytes und was Zeichenketten sind, wo Python 2 einfach ”Zeichenketten” für beides nimmt.

Man muss dazu den Unterschied zwischen Bytes und Zeichenketten kennen. Und für eine sinnvolle Behandlung muss man das grosse ganze vom Programm überblicken, denn das ist eher nichts was man immer lokal an den Stellen löst wo es jetzt gerade kracht. Also man kann sich da nicht sinnvoll von Ausnahme zu Ausnahme im Log hangeln und dann immer an der Stelle wo es gekracht hat was ändern und das Programm dann wieder laufen lassen. Man muss die Punkte im Programm identifizieren wo man das Problem am sinnvollsten beheben kann. Bei Text In der Regel dort, wo die Texte das Programm betreten oder verlassen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@horald: bedenke, dass hier alle FREIWILLIG und UNENTGELDLICH helfen. Die Antwort war immer, dass der Code noch für Python2 geschrieben ist und ein Umschreiben auf Python3 mit größerem Aufwand verbunden ist. Wenn Du die Hinweise hier nicht verstehst, dann liegt das daran, dass Du noch nicht genug Python gelernt hast, um sie zu verstehen. Das Lernen können wir Dir hier nicht abnehmen, und die Lust, triviale Fehler, die man sich durch selbständiges Lernen der Programmiersprache beheben könnte, ist um so geringer, je weniger die/der Beitragsersteller/in erkennen läßt, dass er/sie ernsthaft daran interessiert ist.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Woher kommt deine Vorstellung, nur weil du etwas auf github gekotzt hast, dass da jetzt andere Leute Stunden ihrer Freizeit opfern, dein persoenliches Pet-Projekt ins 21te Jahrhundert zu zerren? Das hat dir niemand versprochen, und das wird auch nicht passieren.

Dir ist sehr konkret der Bereich genannt worden, den du verstehen musst, um diese Probleme SELBST zu loesen. Nochmal die Betonung: SELBST.

Und alles was kommt ist "mimimi, es muss aber deutsch sein, und es muss genau so aussehen wie ich es in meinem Code sehe". Was nicht kommt, ist ein offensichtlicher Versuch, sich mit den gegebenen Hinweisen auseinander zu setzen. Sondern einfach nur mehr Gemecker und der wiederholte Versuch, andere Leute DEINE Arbeit machen zu lassen.

Falls dir das mit deinen ganz offensichtlich nicht ganz jungen Jahren noch nicht aufgegangen sein sollte, hier nochmal in aller Deutlichkeit zum mitschreiben:

Niemand anders als DU bist fuer deinen persoenlichen Erfolg verantwortlich. DU bist derjenige, der Programmieren lernen will, oder muss. Wenn du das Ziel nicht erreichst, dann ist das DEIN Problem. Nicht das von irgendwelchen random Dudes im Internet. Vielleicht ein bisschen von deiner Weiterbildungsstelle, aber wenn dein Verhalten hier ein Hinweis darauf ist, wie du dich da auffuehrst, dann kann man auch die Leute entlasten.

Wir haben dir geholfen. Wir haben dir sehr konkret benannt, woran es hapert. Du stehst im tiefen Tal und hast keine Ahnung welchen Berg du erklimmen sollst. Wir haben dir die Richtung gezeigt. Aber klettern musst du schon selbst, niemand hier ist dein Packesel.
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo zusammen,

ob Ihr es glaubt oder nicht: Das Server-Modul von londonlaw (https://github.com/horald/londonlaw) habe ich jetzt zumindestens ans Laufen gebracht. Beim Client bin ich noch bei der Fehlersuche und das setup.py scheint auch noch nicht richtig zu funktionieren. Trotzdem würde ich es gerne mit anderen spielen. Gibt es denn Leute hier die über Neorouter (http://www.neorouter.com/products-nrfree) es mit mir spielen würden, oder ist es hier das falsche Forum dafür?

Viele Grüße
Horst Meyer
horald
User
Beiträge: 14
Registriert: Dienstag 28. April 2020, 09:10

Hallo Leute,

trotz mangelhafter Unterstützung habe ich londonlaw fertig programmiert! (https://github.com/horald/londonlaw)
Es sind zwar noch kleine Bugs drin, aber man kann es spielen.
Jetzt suche ich nur noch jemanden, der einen VPN-Server hat, damit ich es mal spielen kann... :D

Viele Grüße
Horst
Antworten