손님이 특정 모듈을 볼 수 없지만 여전히 작동하도록 파이썬 코드베이스를 어떻게 보호합니까?
-
22-07-2019 - |
문제
우리는 Python에서 몇 가지 독점 알고리즘과 민감한 논리 비트를 사용하여 새로운 프로젝트를 시작하고 있습니다. 또한 코드에서 작업하는 몇몇 외부인 (대중 선택)이 있습니다. 우리는 외부인에게 소형 개인 비트에 대한 액세스 권한을 부여 할 수는 없지만 공개 버전이 충분히 잘 작동하기를 원합니다.
우리 프로젝트 인 Foo에는 모듈이 있다고 말합니다. bar
, 하나의 기능으로 get_sauce()
. 실제로 무슨 일이 일어나는지 get_sauce()
비밀이지만 우리는 공개 버전을 원합니다. get_sauce()
허용 가능한 것을 반환하려면 부정확하지만 결과.
우리는 또한 우리 자신의 Subversion Server를 실행하므로 누가 액세스 할 수 있는지에 대한 완전히 제어 할 수 있습니다.
Symlinks
나의 첫 번째 생각은 대신에 동성 링크였습니다 bar.py
, 제공하다 bar_public.py
모든 사람과 bar_private.py
내부 개발자에게만. 불행히도, Symlinks를 만드는 것은 지루하고 수동 작업입니다. 특히이 개인 모듈 중 약 24 개가 실제로있을 때.
더 중요한 것은, 각 모듈에 대해 예외를 보호하려는 것이 서버에 추가되어야하기 때문에 Subversion Authz 파일을 관리하기가 어렵다는 것입니다. 누군가 가이 일을 잊고 실수로 비밀을 확인하는 것을 잊을 수 있습니다 ... 그러면 모듈은 리포지토리에 있으며 저장소를 재건해야하며 외부인이 그 동안 다운로드하지 않기를 바랍니다.
여러 저장소
다음 생각에는 두 개의 리포지토리가있는 것이 었습니다.
private
└── trunk/
├── __init__.py
└── foo/
├── __init__.py
└── bar.py
public
└── trunk/
├── __init__.py
└── foo/
├── __init__.py
├── bar.py
├── baz.py
└── quux.py
아이디어는 내부 개발자만이 둘 다 체크 아웃 할 수 있다는 것입니다. private/
그리고 public/
. 내부 개발자는 자신을 설정합니다 PYTHONPATH=private/trunk:public/trunk
, 그러나 다른 모든 사람들은 방금 설정할 것입니다 PYTHONPATH=public/trunk
. 그런 다음 내부자와 외부인 모두가 할 수 있습니다 from foo import bar
그리고 올바른 모듈을 얻으십시오.
이것을 시도해 봅시다 :
% 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
나는 파이썬 전문가가 아니지만 Python은 이미 모듈에 대한 마음을 구성한 것 같습니다. foo
그리고 그것에 대한 검색 :
>>> foo
<module 'foo' from '/path/to/private/trunk/foo/__init__.py'>
삭제조차하지 않습니다 foo
도움 :
>>> 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
더 나은 솔루션이나 제안을 제공 할 수 있습니까?
해결책
에서 __init__
방법의 방법 foo
패키지를 변경할 수 있습니다 __path__
다른 디렉토리에서 모듈을 찾기 위해.
따라서 호출되는 디렉토리를 만듭니다 secret
그리고 당신의 개인 전복 저장소에 넣으십시오. ~ 안에 secret
당신의 독점을 넣으십시오 bar.py
. 에서 __init__.py
대중의 foo
패키지는 다음과 같은 것과 같은 것을 넣습니다.
__path__.insert(0,'secret')
이것은 개인 저장소가있는 사용자에게 의미합니다. secret
디렉토리 그들은 독점을 얻을 것입니다 bar.py
~처럼 foo.bar
~처럼 secret
검색 경로의 첫 번째 디렉토리입니다. 다른 사용자의 경우 Python은 찾을 수 없습니다 secret
다음 디렉토리로 보일 것입니다 __path__
그리고 정상을로드 할 것입니다 bar.py
~에서 foo
.
그래서 그것은 다음과 같이 보일 것입니다.
private
└── trunk/
└── secret/
└── bar.py
public
└── trunk/
├── __init__.py
└── foo/
├── __init__.py
├── bar.py
├── baz.py
└── quux.py
다른 팁
일종의 플러그인 시스템을 사용하고 플러그인을 자체적으로 보관할뿐만 아니라 오픈 코드와 함께 제공되는 공개적으로 사용 가능한 플러그인도 가지고 있습니다.
플러그인 시스템이 많이 있습니다. 당신은 쉽게 죽은 단순한 것을 직접 만들 수 있습니다. 더 진보 된 것을 원한다면 Zope 구성 요소 아키텍처를 선호하지만 setuptools entry_points 등과 같은 옵션도 있습니다.
귀하의 경우에 사용해야 할 것은 좋은 두 번째 질문입니다.
다음은 문서를 읽을 때 알아 차린 대체 솔루션입니다. 플라스크:
flaskext/__init__.py
이 파일의 유일한 목적은 패키지를 네임 스페이스 패키지로 표시하는 것입니다. 다른 PYPI 패키지의 여러 모듈이 동일한 Python 패키지에 상주 할 수 있도록 필요합니다.
__import__('pkg_resources').declare_namespace(__name__)
그곳에서 무슨 일이 일어나고 있는지 정확히 알고 싶다면 배포 또는 SetUptools 문서를 확인하여 이것이 어떻게 작동하는지 설명하십시오.