Seite 1 von 2

random und SystemRandom

Verfasst: Freitag 29. April 2011, 21:44
von mkiever
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

Re: random und SystemRandom

Verfasst: Freitag 29. April 2011, 22:55
von snafu
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?

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 09:30
von mkiever
Ich würde gern in untergeordneten Modulen einfach

Code: Alles auswählen

  import random

  ...
  return random.randint(1, 6)
  ...
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.

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 09:42
von numerix

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()

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 09:52
von mkiever
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

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 10:12
von sma
Diese Weiche müßte ich dann aber in jedem Modul einbauen.
Nicht, wenn du aus dem Beispielcode ein Modul myrandom machst, das du dann überall importierst.

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)
Stefan

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 10:14
von Leonidas
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.

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 11:22
von mkiever
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.

Re: random und SystemRandom

Verfasst: Samstag 30. April 2011, 11:35
von Leonidas
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?
Ne, die würden bedeuten dass du das ``random``-Modul überdeckst und dann da deinen Krams reinsetzt. *blink* *blink* dumme idee *blink* *blink*

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 12:56
von mkiever
So, nach einem Hinweis aus comp.lang.python habe ich jetzt folgendes
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()
Alternativ habe ich noch folgende "monkey-patch" Variante ausprobiert:

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
#...
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

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 13:20
von lunar
@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:

Code: Alles auswählen

from random import SystemRandom
random = SystemRandom()
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?

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 15:48
von mkiever
@lunar:
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.
Tja, wenn's nun mal nicht anders geht.
lunar hat geschrieben:Möchtest Du, dass Deine Module "SystemRandom()" benutzt, dann schreibe sie so um, dass sich das explizit tun:
Das möchte ich gar nicht. Ich möchte:
mkiever hat geschrieben:ich würde bei Start meines Programmes gerne auswählen, ob die Funktionen in random oder die in SystemRandom benutzt werden.
Und zwar, wie im Listing zu sehen, anhand eines Kommandozeilenparameters "-d".
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.
Hmm. Alle diese Module wären nicht wiederverwendbar.
Das ist für mich ein Ausschlußkriterium.
lunar hat geschrieben:Was genau bezweckst du mit dem Gebrauch zweier Unterstriche vor den Namen?!
Ops. Das mußte ich nachschauen. Ich war irgendwie der Meinung,
das ginge auch auf Modulebene zum Markieren von privaten Namen.
Vielen Dank.
lunar hat geschrieben:Und wieso erzeugst Du die OptionParser-Klasse auf Modul-Ebene, wenn Du sie doch genauso gut unterhalb von "__main__" erzeugen könntest?
Ich muß den Umbau mit 'random' machen, bevor sich untergeordnete Module
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.

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 16:14
von /me
mkiever hat geschrieben:Ops. Das mußte ich nachschauen. Ich war irgendwie der Meinung,
das ginge auch auf Modulebene zum Markieren von privaten Namen.
Zum Festlegen von privaten Namen ist _immer_ nur ein führender Unterstrich vorgesehen.

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 16:40
von Leonidas
@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.

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 16:54
von mkiever
@ /me:
/me hat geschrieben:Zum Festlegen von privaten Namen ist _immer_ nur ein führender Unterstrich vorgesehen.
Ich hatte das folgende im Kopf und hatte es auf Module ausgedehnt:

http://docs.python.org/reference/lexica ... dentifiers
__*
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).
Grüße,
Matthias Kievernagel

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 17:26
von mkiever
@ Leonidas:

Der originale Autor bin ich selbst. An der kaputten Struktur ist also definitiv niemand
anders schuld ;-)
Leonidas hat geschrieben:Es ist auch irgendwie nicht ganz klar warum du unbedingt so etwas seltsames machen musst.
Also ich versuche das mal zu erklären.
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.

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 17:37
von lunar
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.

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 17:43
von BlackJack
@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.

Re: random und SystemRandom

Verfasst: Montag 2. Mai 2011, 18:48
von /me
mkiever hat geschrieben:Ich hatte das folgende im Kopf und hatte es auf Module ausgedehnt:

http://docs.python.org/reference/lexica ... dentifiers
Verständlich. Darauf bin ich auch zu Beginn hereingefallen. Das Interessante daran ist allerdings das "mangled form".
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)

Re: random und SystemRandom

Verfasst: Dienstag 3. Mai 2011, 08:24
von lunar
@BlackJack: Auf welchem System blockiert "/dev/urandom" denn? Ich wüsste keines ... es ist halt nur wesentlich langsamer als ein PRNG.