Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从函数进行全局导入?_Python_Import_Module_Python Module - Fatal编程技术网

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

Python 如何从函数进行全局导入?,python,import,module,python-module,Python,Import,Module,Python Module,我担心这是一个混乱的方式来处理这个问题,但 假设我想根据一些条件在Python中进行一些导入 因此,我想编写一个函数: def conditional_import_modules(test): if test == 'foo': import onemodule, anothermodule elif test == 'bar': import thirdmodule, and_another_module else: i

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

假设我想根据一些条件在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()

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

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'>
数学 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 NameError:未定义名称“math” >>>def(): ... 全局数学 ... 输入数学 ... >>>f() >>>数学
您可以在如下函数中使导入全局化:

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

您可以使用内置函数有条件地导入具有全局作用域的模块

要导入顶级模块(请考虑:
import foo
):

从层次结构导入(考虑:
Import foo.bar
):

从层次结构和别名导入(考虑:
将foo.bar导入为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

我喜欢“拉法·格拉比”的方法。因为它甚至支持导入所有。 即 从操作系统导入*

(尽管这是一个坏习惯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
:版本测试在另一个功能中:高出勤率计数最小值:5

我喜欢@maxschlepzig的答案

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

global_imports("tqdm", "tqdm, True)
不工作,因为未导入模块。还有这个

global_imports("tqdm")
global_imports("tqdm", "tqdm, True)
工作

我稍微改变了@maxschlepzig的答案。使用fromlist,以便您可以使用“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)

你能解释一下具体的用例吗?看起来你可以全部导入,然后只使用你需要的模块我想你的意思是==在你的条件下我没有一个真正的用例(意思是我可以用不同的方式解决)但是,当我在编写代码以基于flask web应用程序中的配置文件导入一些蓝图时,我想到了这个问题。我想写一个函数来进行导入,另一个函数来注册它们。@Nicolasbarby Ops。。。手指比大脑快。。。(更正)我喜欢这种方法,但您的代码在这种情况下实际上不起作用。这段代码只返回模块,但实际上没有放入全局变量。看看我的答案,我知道答案并不能完全回答OP的问题。但是,我通常不喜欢操纵globals()。更好的方法是以编程方式在适当的范围内导入正确的模块,IMO(请参阅以获取更多关于这些内容的说明)另外,
importlib
为中的
\uuuuuuuu import\uuuuu
提供了一个包装器。如果在函数my\u imports中执行globals()['ab.cd']=\uu import\uuuu('ab.cd'),模块ab.cd将不会被导入定义my\u imports(modulename,shortname=None):如果shortname为None:shortname=modulename globals()[shortname]=\uuuuuuuuuuuuuu导入(“rpy2”)我的导入(“numpy”,“np”)你确定这合法吗?文档()说全局语句中列出的名称不能定义为形式参数,也不能定义为for循环控制目标、类定义、函数定义或导入语句。“然后它说这对cpython是不强制的,但你不应该这样做。global ab.cd raise aSyntaxError@VY,在这种情况下,您还需要使用
global ab
,cf。作为全局模块,它不也会使所有的东西都在块之外吗?
global_imports("tqdm", "tqdm, True)
global_imports("tqdm")
global_imports("tqdm", "tqdm, True)
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)