Wie schütze ich meine Python Code-Basis, so dass die Gäste nicht bestimmte Module sehen können, aber so funktioniert es immer noch?

StackOverflow https://stackoverflow.com/questions/1443146

Frage

Wir beginnen ein neues Projekt in Python mit einigen proprietären Algorithmen und empfindlichen Bits von Logik, die wir privat halten möchten. Wir haben auch ein paar Außenseiter (ausgewählte Mitglieder der Öffentlichkeit) auf dem Code zu arbeiten. Wir können nicht die Außenseiter zu dem kleinen, privaten Bit-Code zugreifen gewähren, aber wir würden eine öffentliche Version gerne für sie gut genug, um zu arbeiten.

Sagen Sie, dass unser Projekt, Foo, hat ein Modul, bar, mit einer Funktion, get_sauce(). Was passiert wirklich in get_sauce() ist geheim, aber wir wollen eine öffentliche Version von get_sauce() einen akzeptablen zurückzukehren, wenn auch falsch, Ergebnis.

Wir haben auch unseren eigenen Subversion-Server laufen, so dass wir die volle Kontrolle darüber, wer was zugreifen kann.

Symlinks

Mein erster Gedanke war ein SymLink - Statt bar.py bieten bar_public.py an alle und bar_private.py internen Entwickler nur. Leider Symlinks zu schaffen ist mühsam, Handarbeit -. Vor allem, wenn es sich wirklich über zwei Dutzend dieser privaten Module angeschlossen werden

Noch wichtiger ist, macht es Verwaltung der Subversion authz Datei schwierig, da für jedes Modul wollen wir eine Ausnahme schützen muss auf dem Server hinzugefügt werden. Jemand könnte vergessen, dies zu tun und aus Versehen in Geheimnissen überprüft ... Dann wird das Modul in der Repo ist, und wir haben das Repository ohne es neu zu erstellen und hoffen, dass ein Außenseiter Download nicht es in der Zwischenzeit.

Mehrere Repositories

Der nächste Gedanke war, haben zwei Repositories:

private
└── trunk/
    ├── __init__.py
    └── foo/
        ├── __init__.py
        └── bar.py
public
└── trunk/
    ├── __init__.py
    └── foo/
        ├── __init__.py
        ├── bar.py
        ├── baz.py
        └── quux.py

Die Idee ist, dass nur interne Entwickler in der Lage sein werden, sowohl private/ und public/ zur Kasse. Interne Entwickler setzen ihre PYTHONPATH=private/trunk:public/trunk, aber alle anderen werden gerade eingestellt PYTHONPATH=public/trunk. Dann können beide Insider und Outsider from foo import bar und das richtige Modul bekommen, nicht wahr?

Lassen Sie uns versuchen dies:

% PYTHONPATH=private/trunk:public/trunk python
Python 2.5.1
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo.bar
>>> foo.bar.sauce()
'a private bar'
>>> import foo.quux
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named quux

Ich bin kein Python-Experte, aber es scheint, dass Python bereits seine Meinung über Modul foo gemacht hat und sucht im Verhältnis zu:

>>> foo
<module 'foo' from '/path/to/private/trunk/foo/__init__.py'>

Nicht einmal löschen foo hilft:

>>> import sys
>>> del foo
>>> del sys.modules['foo']
>>> import foo.quux
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named quux

Können Sie mich mit einer besseren Lösung oder einen Vorschlag zur Verfügung stellen?

War es hilfreich?

Lösung

Im __init__ Verfahren des foo Paket können Sie ändern, __path__, um es für seine Module in anderen Verzeichnissen zu suchen.

erstellen So ein Verzeichnis namens secret und steckt es in Ihrer privaten Subversion-Repository. In secret setzen Sie Ihre proprietäre bar.py. Im __init__.py des öffentlichen foo Pakets in etwas setzen wie:

__path__.insert(0,'secret')

Dies wird für die Nutzer, wer die privaten Repository haben und so das secret Verzeichnis werden sie den proprietären bar.py als foo.bar als secret bekommen das erste Verzeichnis im Suchpfad ist. Für andere Benutzer wird Python nicht secret findet und wird als das nächste Verzeichnis in __path__ aussehen und so wird die normalen bar.py von foo laden.

So ist es so etwas wie folgt aussehen:

   private
    └── trunk/
        └── secret/
            └── bar.py
    public
    └── trunk/
        ├── __init__.py
        └── foo/
            ├── __init__.py
            ├── bar.py
            ├── baz.py
            └── quux.py

Andere Tipps

eine Art Plugin-System verwenden, und halten Sie Ihre Plugins, um sich selbst, sondern auch öffentlich verfügbaren Plugins, die mit dem offenen Code ausgeliefert wird.

Plugin-Systeme gibt es zuhauf. Sie können ganz einfach tot einfach knüpfen sich. Wenn Sie etwas weiter fortgeschritten wollen bevorzuge ich die Zope Component Architecture, aber es gibt auch Optionen, wie Setuptools entry_points, etc.

Welche in Ihrem Fall zu verwenden, wäre eine gute zweite Frage sein.

Hier ist eine alternative Lösung, die ich bemerkt, wenn die Dokumentation zu lesen für Flask :

  

flaskext/__init__.py

     

Der einzige Zweck dieser Datei ist das Paket als Namespace-Paket zu markieren. Dies ist erforderlich, so dass mehrere Module aus verschiedenen PyPI Paketen können in dem gleichen Python-Paket befinden:

__import__('pkg_resources').declare_namespace(__name__)
     

Wenn Sie genau wissen wollen, was dort geschieht, Check-out die verteilen oder Setuptools Dokumente, die erklären, wie das funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top