これは問題にアプローチするための厄介な方法ではないかと心配していますが...
いくつかの条件に基づいて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)
いくつかのバグがある可能性があり、それらを確認して更新します。最後の例には、別の「ショートネーム」または「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__)