Hallo Liebe Leute,
ich würde bei Start meines Programmes gerne
auswählen, ob die Funktionen in random oder die in SystemRandom
benutzt werden. Wie macht man so etwas prinzipiell ?
Kennt jemand eine Referenz auf ein 'recipe', das so etwas oder etwas
Vergleichbares macht ? Ach ja, ein Schlagwort auf die Technik würde
mir auch schon helfen.
Grüße,
Matthias Kievernagel
random und SystemRandom
Da beide die selbem Methoden haben (auch wenn manche bei SystemRandom nichts tun), kannst du einfach eine der Klassen bzw Exemplare als Argument erwarten und darauf dann arbeiten. Oder was meinst du genau?
Ich würde gern in untergeordneten Modulen einfach
haben und im TopLevel-Script festlegen, ob das random.xxx oder random.SystemRandom.xxx
bedeutet. In C würde ich das im Makefile mit Compiler- / Link-Optionen machen
(DEBUG / FINAL - Build).
Ich hoffe, die Absicht ist jetzt klarer.
Matthias Kievernagel.
Code: Alles auswählen
import random
...
return random.randint(1, 6)
...
bedeutet. In C würde ich das im Makefile mit Compiler- / Link-Optionen machen
(DEBUG / FINAL - Build).
Ich hoffe, die Absicht ist jetzt klarer.
Matthias Kievernagel.
Code: Alles auswählen
import random
SYSRANDOM = True
myrandom = random.SystemRandom() if SYSRANDOM else random
print myrandom.randint(2,8)
print myrandom.randrange(3,19)
print myrandom.random()
Diese Weiche müßte ich dann aber in jedem Modul einbauen.
Ich hätte eigentlich gern, daß untergeordnete Module
von der Umschaltung gar nichts wissen und einfach
ganz blöd den Code aus meinem vorhergegangenen Posting
enthalten (Weiterverwendbarkeit, etc...).
Danke für den Vorschlag,
Matthias Kievernagel
Ich hätte eigentlich gern, daß untergeordnete Module
von der Umschaltung gar nichts wissen und einfach
ganz blöd den Code aus meinem vorhergegangenen Posting
enthalten (Weiterverwendbarkeit, etc...).
Danke für den Vorschlag,
Matthias Kievernagel
Nicht, wenn du aus dem Beispielcode ein Modul myrandom machst, das du dann überall importierst.Diese Weiche müßte ich dann aber in jedem Modul einbauen.
Code: Alles auswählen
# dies ist myrandom.py
import random
SYSRANDOM = True
_m = random.SystemRandom() if SYSRANDOM else random
randint = _m.randint
random = _m.random
# dies ist dein Code
from myrandom import randint
print randint(1, 6)
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Nein, so ohne weiteres geht das (ohne Verrenkungen nicht). Du solltest besser ein eigenes random-Modul schreiben mit der Weiche und dann auf dieses aus Untermodulen zugreifen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Ich habe ja inzwischen auch etwas nachgedacht :-)
Die "Verrenkungen" würde Herumbasteln am importierten
random 'module'-Objekt (bzw. Ersetzen durch ein Fake) bedeuten?
Liege ich da in etwa richtig?
An den Import-Mechanismus muß man aber nicht ran,
wenn 'random' schon importiert ist, wird es ja nicht erneut
geladen, oder?
Vielen Dank,
Matthias Kievernagel
PS: Ich habe auch mal 'ne Anfrage in comp.lang.python gestartet.
Wenn da etwas herauskommt, fasse ich das hier mal zusammen.
Die "Verrenkungen" würde Herumbasteln am importierten
random 'module'-Objekt (bzw. Ersetzen durch ein Fake) bedeuten?
Liege ich da in etwa richtig?
An den Import-Mechanismus muß man aber nicht ran,
wenn 'random' schon importiert ist, wird es ja nicht erneut
geladen, oder?
Vielen Dank,
Matthias Kievernagel
PS: Ich habe auch mal 'ne Anfrage in comp.lang.python gestartet.
Wenn da etwas herauskommt, fasse ich das hier mal zusammen.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ne, die würden bedeuten dass du das ``random``-Modul überdeckst und dann da deinen Krams reinsetzt. *blink* *blink* dumme idee *blink* *blink*mkiever hat geschrieben:Ich habe ja inzwischen auch etwas nachgedacht
Die "Verrenkungen" würde Herumbasteln am importierten
random 'module'-Objekt (bzw. Ersetzen durch ein Fake) bedeuten?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
So, nach einem Hinweis aus comp.lang.python habe ich jetzt folgendes
Funktionsfähiges zusammengebaut:
Alternativ habe ich noch folgende "monkey-patch" Variante ausprobiert:
Funktioniert auch. Obige Variante gefällt mir besser, da ich da gleich
eine Fehlermeldung bekomme, falls irgendetwas Untergeordnetes versucht,
SystemRandom direkt zu benutzen.
Grüße,
Matthias Kievernagel
Funktionsfähiges zusammengebaut:
Code: Alles auswählen
from optparse import OptionParser
import random
import sys
__op = OptionParser()
__op.add_option('-d', '--debug',
help='debug build with fixed random generator',
action="store_true", dest='debugFlag', default=False)
(__opts, __args) = __op.parse_args()
if not __opts.debugFlag:
#print('setup using SystemRandom')
sys.modules['random'] = random.SystemRandom()
# ... alle weiteren Importe
# ... die Applikationsklasse
if __name__ == '__main__':
b = BritApp()
b.setup(prefix=__opts.pathPrefix, debug=__opts.debugFlag)
b.cmdloop()
Code: Alles auswählen
#...
if not __opts.debugFlag:
#print('setup using SystemRandom')
sr = random.SystemRandom()
random.choice = sr.choice
random.getrandbits = sr.getrandbits
random.getstate = sr.getstate
random.randint = sr.randint
random.random = sr.random
random.randrange = sr.randrange
random.sample = sr.sample
random.seed = sr.seed
random.setstate = sr.setstate
random.shuffle = sr.shuffle
#...
eine Fehlermeldung bekomme, falls irgendetwas Untergeordnetes versucht,
SystemRandom direkt zu benutzen.
Grüße,
Matthias Kievernagel
@mkiever: Der Hinweis von Leonidas, dass es sich dabei um eine „dumme Idee“ handelt, war durchaus ernst gemeint. Im Allgemeinen werden solche „Hacks“ ziemlich kritisch gesehen. Möchtest Du, dass Deine Module "SystemRandom()" benutzt, dann schreibe sie so um, dass sich das explizit tun:
Wenn Dir das zu viel Arbeit ist, spricht das nicht für Deine Methode, sondern eher gegen Deinen Quelltext, welcher dann so restrukturiert werden sollte, dass die Erzeugung des Zufallsgenerators nur an einer Stelle stattfindet, beispielsweise indem Du im Toplevel-Paket Deiner Anwendung obigen Quelltext einfügst, und anschließend in den anderen Modulen "from myapp import random" nutzt.
Was genau bezweckst du mit dem Gebrauch zweier Unterstriche vor den Namen?! Und wieso erzeugst Du die OptionParser-Klasse auf Modul-Ebene, wenn Du sie doch genauso gut unterhalb von "__main__" erzeugen könntest?
Code: Alles auswählen
from random import SystemRandom
random = SystemRandom()
Was genau bezweckst du mit dem Gebrauch zweier Unterstriche vor den Namen?! Und wieso erzeugst Du die OptionParser-Klasse auf Modul-Ebene, wenn Du sie doch genauso gut unterhalb von "__main__" erzeugen könntest?
@lunar:
Das ist für mich ein Ausschlußkriterium.
das ginge auch auf Modulebene zum Markieren von privaten Namen.
Vielen Dank.
ggf. mit "from random import randint" Zugriff auf die falsche Funktion verschaffen.
Aber es sollte trotzdem mit einem "if __name__ == '__main__':" versehen sein, korrekt.
Grüße,
Matthias Kievernagel.
Tja, wenn's nun mal nicht anders geht.lunar hat geschrieben:Der Hinweis von Leonidas, dass es sich dabei um eine „dumme Idee“ handelt, war durchaus ernst gemeint. Im Allgemeinen werden solche „Hacks“ ziemlich kritisch gesehen.
Das möchte ich gar nicht. Ich möchte:lunar hat geschrieben:Möchtest Du, dass Deine Module "SystemRandom()" benutzt, dann schreibe sie so um, dass sich das explizit tun:
Und zwar, wie im Listing zu sehen, anhand eines Kommandozeilenparameters "-d".mkiever hat geschrieben:ich würde bei Start meines Programmes gerne auswählen, ob die Funktionen in random oder die in SystemRandom benutzt werden.
Hmm. Alle diese Module wären nicht wiederverwendbar.lunar hat geschrieben:beispielsweise indem Du im Toplevel-Paket Deiner Anwendung obigen Quelltext einfügst, und anschließend in den anderen Modulen "from myapp import random" nutzt.
Das ist für mich ein Ausschlußkriterium.
Ops. Das mußte ich nachschauen. Ich war irgendwie der Meinung,lunar hat geschrieben:Was genau bezweckst du mit dem Gebrauch zweier Unterstriche vor den Namen?!
das ginge auch auf Modulebene zum Markieren von privaten Namen.
Vielen Dank.
Ich muß den Umbau mit 'random' machen, bevor sich untergeordnete Modulelunar hat geschrieben:Und wieso erzeugst Du die OptionParser-Klasse auf Modul-Ebene, wenn Du sie doch genauso gut unterhalb von "__main__" erzeugen könntest?
ggf. mit "from random import randint" Zugriff auf die falsche Funktion verschaffen.
Aber es sollte trotzdem mit einem "if __name__ == '__main__':" versehen sein, korrekt.
Grüße,
Matthias Kievernagel.
Zum Festlegen von privaten Namen ist _immer_ nur ein führender Unterstrich vorgesehen.mkiever hat geschrieben:Ops. Das mußte ich nachschauen. Ich war irgendwie der Meinung,
das ginge auch auf Modulebene zum Markieren von privaten Namen.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
@mkiever: Das klingt nach nem furchtbar kaputten Programm dass du da monkeypatcht. Kannst du es nicht einfach umschreiben, damits nicht mehr so kaputt ist? Vielleicht gegebenfalls ein paar Patches an den ursprünglichen Autor? Es ist auch irgendwie nicht ganz klar warum du unbedingt so etwas seltsames machen musst.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@ /me:
http://docs.python.org/reference/lexica ... dentifiers
Matthias Kievernagel
Ich hatte das folgende im Kopf und hatte es auf Module ausgedehnt:/me hat geschrieben:Zum Festlegen von privaten Namen ist _immer_ nur ein führender Unterstrich vorgesehen.
http://docs.python.org/reference/lexica ... dentifiers
Grüße,__*
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes. See section Identifiers (Names).
Matthias Kievernagel
@ Leonidas:
Der originale Autor bin ich selbst. An der kaputten Struktur ist also definitiv niemand
anders schuld
Vorweg gebe ich gleich mal zu, daß ich das ganze Thema verschärft habe, indem ich
random und SystemRandom alternativ haben wollte. Für den Applikationsbereich (Spiel)
würde sicherlich random mit konstantem Seed vs. random mit time Seed ausreichen.
Aber dann wollte ich gucken wie man das machen würde - es gibt ja durchaus Bereiche
in denen SystemRandom für eine finale Version unumgänglich wäre.
Für die debug-Version will ich einfach einen Zufallsgenerator haben, der eine scheint's
zufällige Folge von Zahlen liefert, aber eben jedesmal dieselbe. Die echte Version
soll eben richtig zufällige Zahlen verwenden. Das ganze gesteuert über einen
Kommandozeilenparameter. SystemRandom hat eben den Nachteil, daß es
"richtig" zufällig ist und keine wiederholbaren Folgen liefern kann.
Einige hatten ein Modul "myrandom" oder ein Zugriff auf random in der Applikationsklasse
vorgeschlagen. Das gefällt mir überhaupt nicht, da es die Weiterverwendung der Module unmöglich machen
würde. Oder gibt es dafür Beispiele in existierenden Modulen / Bibliotheken ?
Ich hoffe, damit ist meine Absicht etwas klarer.
Matthias Kievernagel.
Der originale Autor bin ich selbst. An der kaputten Struktur ist also definitiv niemand
anders schuld

Also ich versuche das mal zu erklären.Leonidas hat geschrieben:Es ist auch irgendwie nicht ganz klar warum du unbedingt so etwas seltsames machen musst.
Vorweg gebe ich gleich mal zu, daß ich das ganze Thema verschärft habe, indem ich
random und SystemRandom alternativ haben wollte. Für den Applikationsbereich (Spiel)
würde sicherlich random mit konstantem Seed vs. random mit time Seed ausreichen.
Aber dann wollte ich gucken wie man das machen würde - es gibt ja durchaus Bereiche
in denen SystemRandom für eine finale Version unumgänglich wäre.
Für die debug-Version will ich einfach einen Zufallsgenerator haben, der eine scheint's
zufällige Folge von Zahlen liefert, aber eben jedesmal dieselbe. Die echte Version
soll eben richtig zufällige Zahlen verwenden. Das ganze gesteuert über einen
Kommandozeilenparameter. SystemRandom hat eben den Nachteil, daß es
"richtig" zufällig ist und keine wiederholbaren Folgen liefern kann.
Einige hatten ein Modul "myrandom" oder ein Zugriff auf random in der Applikationsklasse
vorgeschlagen. Das gefällt mir überhaupt nicht, da es die Weiterverwendung der Module unmöglich machen
würde. Oder gibt es dafür Beispiele in existierenden Modulen / Bibliotheken ?
Ich hoffe, damit ist meine Absicht etwas klarer.
Matthias Kievernagel.
Beim Monkey-Patchen globaler Module sind Deine eigenen Module nicht mehr und nicht weniger wiederverwendbar als bei der Nutzung eines eigenen Random-Moduls. Eine Abhängigkeit besteht so oder so, nur eben zu einem anderen Modul. Beim eigenen Modul ist die Abhängigkeit aber wenigstens explizit, so dass man auch nach sechs Monaten noch versteht, was da passiert.
Wenn Dir der Lösungsansatz über ein Modul nicht gefällt, dann erzeuge eben ein Exemplar des Zufallsgenerators an zentraler Stelle und reiche es an die Klassen und Funktionen, die einen Zufallsgenerator benötigen, durch. Alternativ kannst Du auch die Klasse des Zufallsgenerators übergeben.
Das Argument „geht nicht anders“ lasse ich nicht gelten. Es geht immer anders, man muss es nur wollen. Mag sein, dass eine explizite Lösung aufwendiger ist als das Monkey-Patchen, dafür ist sie leichter zu testen, verständlicher und wartbarer und somit auf lange Sicht sinnvoller.
Wenn Dir der Lösungsansatz über ein Modul nicht gefällt, dann erzeuge eben ein Exemplar des Zufallsgenerators an zentraler Stelle und reiche es an die Klassen und Funktionen, die einen Zufallsgenerator benötigen, durch. Alternativ kannst Du auch die Klasse des Zufallsgenerators übergeben.
Das Argument „geht nicht anders“ lasse ich nicht gelten. Es geht immer anders, man muss es nur wollen. Mag sein, dass eine explizite Lösung aufwendiger ist als das Monkey-Patchen, dafür ist sie leichter zu testen, verständlicher und wartbarer und somit auf lange Sicht sinnvoller.
@mkiever: Sauber gelöst würde man halt überall wo Zufall erzeugt werden soll nicht fest auf das `random`-Modul zugreifen, sondern das Objekt als Argument übergeben. Oder eben auf ein "Zwischenmodul" zugreifen. Wobei ich nicht ganz verstehe was das mit dem "nicht wiederverwendbar" auf sich hat. Natürlich kann man die Module wiederverwenden. Man muss halt nur ein `myrandom`-Modul zur Verfügung stellen.
Von `SystemRandom` würde ich in einem Spiel wohl auch die Finger lassen. Je nach System und Implementierung kann die Erzeugung von Zufallszahlen blockieren wenn das System meint es hat nicht genügend "Entropie gesammelt" um Zahlen zu liefern die zufällig genug sind. Die Funktion kehrt dann zum Beispiel erst zurück wenn genug Tastatur- und Mausaktivität vom Benutzer kam.
Feste vs. "zufällige" Folge kannst Du mit dem normalen `random` einfacher haben. Wenn fest, dann `random.seed()`-Aufrufen, sonst gar nichts machen.
Von `SystemRandom` würde ich in einem Spiel wohl auch die Finger lassen. Je nach System und Implementierung kann die Erzeugung von Zufallszahlen blockieren wenn das System meint es hat nicht genügend "Entropie gesammelt" um Zahlen zu liefern die zufällig genug sind. Die Funktion kehrt dann zum Beispiel erst zurück wenn genug Tastatur- und Mausaktivität vom Benutzer kam.
Feste vs. "zufällige" Folge kannst Du mit dem normalen `random` einfacher haben. Wenn fest, dann `random.seed()`-Aufrufen, sonst gar nichts machen.
Verständlich. Darauf bin ich auch zu Beginn hereingefallen. Das Interessante daran ist allerdings das "mangled form".mkiever hat geschrieben:Ich hatte das folgende im Kopf und hatte es auf Module ausgedehnt:
http://docs.python.org/reference/lexica ... dentifiers
Schau dir mal an, was im Namensraum passiert wenn du zwei Unterstriche verwendest.
Code: Alles auswählen
class Foo(object):
_bar = 'x'
__baz = 'y'
print dir(Foo)
class Foobar(Foo):
_bar = 'a'
__baz = 'b'
print dir(Foobar)
@BlackJack: Auf welchem System blockiert "/dev/urandom" denn? Ich wüsste keines ... es ist halt nur wesentlich langsamer als ein PRNG.