IT이야기

함수에서 전역 가져오기를 수행하는 방법

cyworld 2021. 10. 5. 21:21
반응형

함수에서 전역 가져오기를 수행하는 방법은 무엇입니까?


나는 이것이 문제에 접근하는 지저분한 방법이라고 두려워하지만 ...

일부 조건에 따라 Python에서 일부 가져오기를 만들고 싶다고 가정해 보겠습니다.

이러한 이유로 함수를 작성하고 싶습니다.

def conditional_import_modules(test):
    if test == 'foo':
        import onemodule, anothermodule
    elif test == 'bar':
        import thirdmodule, and_another_module
    else:
        import all_the_other_modules

이제 가져온 모듈을 전역적으로 사용할 수 있게 하려면 어떻게 해야 합니까?

예를 들어:

conditional_import_modules(test='bar')
thirdmodule.myfunction()

가져온 모듈은 변수일 뿐입니다. 이름은 일부 값에 바인딩됩니다. 따라서 필요한 것은 가져 와서 global키워드로 전역으로 만드는 것 입니다.

예시:

>>> math
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'math' is not defined
>>> def f():
...     global math
...     import math
...
>>> f()
>>> math
<module 'math' from '/usr/local/lib/python2.6/lib-dynload/math.so'>

다음과 같이 함수 내에서 가져오기를 전역으로 만들 수 있습니다.

def my_imports(module_name):
    globals()[module_name] = __import__(module_name)

이 함수가 가져오려는 모듈의 이름을 반환하고 다음을 사용하도록 할 수 있습니다.

mod == __import__(module_name)

내장 함수 __import__사용하여 전역 범위의 모듈을 조건부로 가져올 수 있습니다 .

최상위 모듈을 가져오려면(생각: import foo):

def cond_import():
  global foo
  foo = __import__('foo', globals(), locals()) 

계층에서 가져오기(생각: import foo.bar):

def cond_import():
  global foo
  foo = __import__('foo.bar', globals(), locals()) 

계층 및 별칭에서 가져오기(생각: import foo.bar as bar):

def cond_import():
  global bar
  foo = __import__('foo.bar', globals(), locals()) 
  bar = foo.bar

@badzil 접근 방식을 좋아합니다.

def global_imports(modulename,shortname = None, asfunction = False):
    if shortname is None: 
        shortname = modulename
    if asfunction is False:
        globals()[shortname] = __import__(modulename)
    else:        
        globals()[shortname] = eval(modulename + "." + shortname)

따라서 전통적으로 클래스 모듈에 있는 것:

import numpy as np

import rpy2
import rpy2.robjects as robjects
import rpy2.robjects.packages as rpackages
from rpy2.robjects.packages import importr

전역 범위로 변환할 수 있습니다.

global_imports("numpy","np")

global_imports("rpy2")
global_imports("rpy2.robjects","robjects")
global_imports("rpy2.robjects.packages","rpackages")
global_imports("rpy2.robjects.packages","importr",True)

일부 버그가 있을 수 있으며 확인하고 업데이트하겠습니다. 마지막 예제에는 다른 "shortname" 또는 "importr|aliasimportr"과 같은 해킹이 있는 별칭이 있을 수도 있습니다.


방금 비슷한 문제가 발생했습니다. 여기 내 해결책이 있습니다.

class GlobalImport:

    def __enter__(self):
        return self

    def __call__(self):
        import inspect
        self.collector = inspect.getargvalues(inspect.getouterframes(inspect.currentframe())[1].frame).locals

    def __exit__(self, *args):
        globals().update(self.collector)

그런 다음 코드의 아무 곳에서나 다음을 수행합니다.

with GlobalImport() as gi:
    import os, signal, atexit, threading, _thread
    # whatever you want it won't remain local
    # if only 
    gi()
    # is called before the end of this block

# there you go: use os, signal, ... from whatever place of the module

나는 @rafał Grabie 접근 방식을 좋아합니다. 모두 가져오기를 지원하기 때문입니다. 즉 os 가져오기에서 *

(나쁜 습관에도 불구하고 XD)

댓글은 허용되지 않지만 여기 python 2.7 버전이 있습니다.

또한 마지막에 함수를 호출할 필요가 제거되었습니다.

class GlobalImport:
    def __enter__(self):
        return self
    def __exit__(self, *args):
        import inspect
        collector = inspect.getargvalues(inspect.getouterframes(inspect.currentframe())[1][0]).locals
        globals().update(collector)

def test():
    with GlobalImport() as gi:
        ## will fire a warning as its bad practice for python. 
        from os import *

test()
print path.exists(__file__)

ReferenceURL : https://stackoverflow.com/questions/11990556/how-to-make-global-imports-from-a-function

반응형