如何从函数进行全局导入?

我担心这是一个混乱的方式来处理问题,但..。

假设我想在 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()
64230 次浏览

您可以让此函数返回要导入的模块的名称,然后使用

mod == __import__(module_name)

导入的模块只是变量-名称绑定到一些值。所以你需要做的就是导入它们,然后用 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)

可以使用内置函数 __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)

可能有一些错误,我将验证和更新。最后一个例子也可以有一个别名,它可以是另一个“短名称”或者类似于“ import r | aliasimport r”的黑客

我也遇到过类似的问题,以下是我的解决方案:

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 的方法,因为它甚至支持导入所有。 也就是说。 从操作系统进口 *

(尽管这是不好的做法 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__)

步骤1: 同一目录/文件夹中的 config.py、 config _ v2.py 和 rnd.py

步骤2: config.py

HIGH_ATTENDANCE_COUNT_MIN = 0

步骤3: config _ v2. py

HIGH_ATTENDANCE_COUNT_MIN = 5

步骤4: rnd.py

def versioning_test(v):
global config


if v == 'v1':
config = __import__('config', globals(), locals())
    

if v == 'v2':
config = __import__('config_v2', globals(), locals())


def version_test_in_another_function():
print('version_test_in_another_function: HIGH_ATTENDANCE_COUNT_MIN: ', config.HIGH_ATTENDANCE_COUNT_MIN)
 



versioning_test("v2")
version_test_in_another_function()

步骤5: $python3 rnd.py

<<output>>: version_test_in_another_function: HIGH_ATTENDANCE_COUNT_MIN:  5

我喜欢@maxschleppzig 的回答。

这种方法存在一个 bug,即如果直接导入函数,它将无法工作。 比如说,

global_imports("tqdm", "tqdm, True)

不能工作,因为模块没有被导入

global_imports("tqdm")
global_imports("tqdm", "tqdm, True)

工程。

我稍微改了一下@maxschlepig 的回答。使用 FROM list,以便能够以统一的方式用“ From”语句加载函数或模块。

def global_imports(object_name: str,
short_name: str = None,
context_module_name: str = None):
"""import from local function as global import


Use this statement to import inside a function,
but effective as import at the top of the module.


Args:
object_name: the object name want to import,
could be module or function
short_name: the short name for the import
context_module_name: the context module name in the import


example usage:
import os -> global_imports("os")
import numpy as np -> global_imports("numpy", "np")
from collections import Counter ->
global_imports("Counter", None, "collections")
from google.cloud import storage ->
global_imports("storage", None, "google.cloud")


"""
if not short_name:
short_name = object_name
if not context_module_name:
globals()[short_name] = __import__(object_name)
else:
context_module = __import__(context_module_name,
fromlist=[object_name])
globals()[short_name] = getattr(context_module, object_name)