[PYTHON] 파이썬에서 문자열로부터 모듈로드하기
PYTHON파이썬에서 문자열로부터 모듈로드하기
나는 문자열의 형태로 몇 가지 코드를 가지고 있으며 디스크에 쓰지 않고 모듈을 만들고 싶습니다.
imp 및 StringIO 객체를 사용하여이 작업을 수행하면 다음과 같이 나타납니다.
>>> imp.load_source('my_module', '', StringIO('print "hello world"'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: load_source() argument 3 must be file, not instance
>>> imp.load_module('my_module', StringIO('print "hello world"'), '', ('', '', 0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: load_module arg#2 should be a file or None
실제 파일이 없어도 모듈을 만들려면 어떻게해야합니까? 또는 디스크에 쓰지 않고 파일에서 StringIO를 어떻게 랩핑 할 수 있습니까?
최신 정보:
참고 :이 문제는 또한 python3의 문제입니다.
로드하려고하는 코드는 부분적으로 만 신뢰할 수 있습니다. 나는 ast를 통해 그걸 가져 왔고, 아무것도 가져 오지 않거나 좋지 않은 일을한다고 결정했다. 그러나 그 주위를 돌고있는 지역 변수가있을 때 그것을 실행할만큼 충분히 신뢰하지 않는다. 내가 가져 오려고하는 코드의 방해가되지 않도록 내 자신의 코드를 신뢰하지 않습니다.
다음을 포함하는 빈 모듈을 만들었습니다.
def load(code):
# Delete all local variables
globals()['code'] = code
del locals()['code']
# Run the code
exec(globals()['code'])
# Delete any global variables we've added
del globals()['load']
del globals()['code']
# Copy k so we can use it
if 'k' in locals():
globals()['k'] = locals()['k']
del locals()['k']
# Copy the rest of the variables
for k in locals().keys():
globals()[k] = locals()[k]
그런 다음 mymodule을 가져 와서 mymodule.load (code)를 호출 할 수 있습니다. 이것은 내가로드하는 코드가 전역을 사용하지 않도록하기 때문에 저에게 효과적입니다. 또한 global 키워드는 구문 분석기 지시문 일 뿐이며 exec 외부의 것은 참조 할 수 없습니다.
이것은 실제로 디스크에 쓰지 않고 모듈을 가져 오는 데 너무 많은 작업이지만, 이것을 원한다면 가장 좋은 방법이라고 생각합니다.
해결법
-
==============================
1.다음은 문자열을 모듈로 가져 오는 방법입니다 (Python 2.x).
다음은 문자열을 모듈로 가져 오는 방법입니다 (Python 2.x).
import sys,imp my_code = 'a = 5' mymodule = imp.new_module('mymodule') exec my_code in mymodule.__dict__
파이썬 3에서 exec는 함수이므로 다음과 같이 작동해야합니다.
import sys,imp my_code = 'a = 5' mymodule = imp.new_module('mymodule') exec(my_code, mymodule.__dict__)
이제 모듈 속성 (및 함수, 클래스 등)에 액세스합니다.
print(mymodule.a) >>> 5
가져올 다음 시도를 무시하려면 모듈을 sys :
sys.modules['mymodule'] = mymodule
-
==============================
2.모듈의 코드가 문자열에 있으면 StringIO를 사용하지 않고 exec와 함께 직접 사용할 수 있습니다 (아래에 dynmodule.py라는 파일이 있음). Python 2 및 3에서 작동합니다.
모듈의 코드가 문자열에 있으면 StringIO를 사용하지 않고 exec와 함께 직접 사용할 수 있습니다 (아래에 dynmodule.py라는 파일이 있음). Python 2 및 3에서 작동합니다.
from __future__ import print_function class _DynamicModule(object): def load(self, code): execdict = {'__builtins__': None} # optional, to increase safety exec(code, execdict) keys = execdict.get( '__all__', # use __all__ attribute if defined # else all non-private attributes (key for key in execdict if not key.startswith('_'))) for key in keys: setattr(self, key, execdict[key]) # replace this module object in sys.modules with empty _DynamicModule instance # see Stack Overflow question: http://bit.ly/ff94g6) import sys as _sys _ref, _sys.modules[__name__] = _sys.modules[__name__], _DynamicModule() if __name__ == '__main__': import dynmodule # name of this module import textwrap # for more readable code formatting in sample string # string to be loaded can come from anywhere or be generated on-the-fly module_code = textwrap.dedent("""\ foo, bar, baz = 5, 8, 2 def func(): return foo*bar + baz __all__ = 'foo', 'bar', 'func' # 'baz' not included """) dynmodule.load(module_code) # defines module's contents print('dynmodule.foo:', dynmodule.foo) try: print('dynmodule.baz:', dynmodule.baz) except AttributeError: print('no dynmodule.baz attribute was defined') else: print('Error: there should be no dynmodule.baz module attribute') print('dynmodule.func() returned:', dynmodule.func())
산출:
dynmodule.foo: 5 no dynmodule.baz attribute was defined dynmodule.func() returned: 42
execdict 사전에서 '__builtins__'항목을 없음으로 설정하면 코드가 __import__와 같은 내장 함수를 직접 실행하지 못하도록하므로 코드를 더 안전하게 실행합니다. 당신은 당신이 느끼고있는 것들을 선별 적으로 추가함으로써 그러한 제한을 완화 할 수 있습니다.
코드에서 사용할 수있게하려는 미리 정의 된 유틸리티와 속성을 추가하여 해당 코드가 실행될 사용자 정의 실행 컨텍스트를 만들 수도 있습니다. 이런 종류의 일은 "플러그인"또는 다른 플러그인을 구현하는 데 유용 할 수 있습니다 사용자 확장 가능 아키텍처.
-
==============================
3.간단히 Module 객체를 만들고이를 sys.modules에 채우고 코드를 내부에 넣을 수 있습니다.
간단히 Module 객체를 만들고이를 sys.modules에 채우고 코드를 내부에 넣을 수 있습니다.
같은 것 :
import sys from types import ModuleType mod = ModuleType('mymodule') sys.modules['mymodule'] = mod exec(mycode, mod.__dict__)
-
==============================
4.exec 또는 eval을 사용하여 파이썬 코드를 문자열로 실행할 수 있습니다. 여기, 여기, 여기를 참조하십시오.
exec 또는 eval을 사용하여 파이썬 코드를 문자열로 실행할 수 있습니다. 여기, 여기, 여기를 참조하십시오.
-
==============================
5.imp.load_source에 대한 문서는 (필자의 강조) :
imp.load_source에 대한 문서는 (필자의 강조) :
...이 방법으로 운이 나빠질 수도 있습니다, 두렵습니다.
아마도이 경우 eval만으로도 충분할 것입니까?
이것은 다소 놀라운 요구 사항처럼 들리지만 실제로 해결하려고하는 문제에 대해 질문에 더 추가하면 도움이 될 수 있습니다.
from https://stackoverflow.com/questions/5362771/load-module-from-string-in-python by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 파이썬에서 문자열을 정수로 분리하는 방법은? (0) | 2018.10.04 |
---|---|
[PYTHON] Python을 사용하여 Windows에서 폴더 권한 설정 (0) | 2018.10.04 |
[PYTHON] 도커에 최소 플라스크 앱 배포 - 서버 연결 문제 (0) | 2018.10.04 |
[PYTHON] 사용자 정의 팝업 tkinter 대화 상자를 구현하는 올바른 방법 (0) | 2018.10.04 |
[PYTHON] for 중첩 된 루프 방지하기 (0) | 2018.10.04 |