当前位置: 首页 > 面试题库 >

在Python中模拟ImportError

平元明
2023-03-14
问题内容

我正在尝试近两个小时,没有任何运气。

我有一个看起来像这样的模块:

try:
    from zope.component import queryUtility  # and things like this
except ImportError:
    # do some fallback operations <-- how to test this?

稍后在代码中:

try:
    queryUtility(foo)
except NameError:
    # do some fallback actions <-- this one is easy with mocking 
    # zope.component.queryUtility to raise a NameError

有任何想法吗?

编辑:

亚历克斯的建议似乎无效:

>>> import __builtin__
>>> realimport = __builtin__.__import__
>>> def fakeimport(name, *args, **kw):
...     if name == 'zope.component':
...         raise ImportError
...     realimport(name, *args, **kw)
...
>>> __builtin__.__import__ = fakeimport

运行测试时:

aatiis@aiur ~/work/ao.shorturl $ ./bin/test --coverage .
Running zope.testing.testrunner.layer.UnitTests tests:
  Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds.


Error in test /home/aatiis/work/ao.shorturl/src/ao/shorturl/shorturl.txt
Traceback (most recent call last):
  File "/usr/lib64/python2.5/unittest.py", line 260, in run
    testMethod()
  File "/usr/lib64/python2.5/doctest.py", line 2123, in runTest
    test, out=new.write, clear_globs=False)
  File "/usr/lib64/python2.5/doctest.py", line 1361, in run
    return self.__run(test, compileflags, out)
  File "/usr/lib64/python2.5/doctest.py", line 1282, in __run
    exc_info)
  File "/usr/lib64/python2.5/doctest.py", line 1148, in report_unexpected_exception
    'Exception raised:\n' + _indent(_exception_traceback(exc_info)))
  File "/usr/lib64/python2.5/doctest.py", line 1163, in _failure_header
    out.append(_indent(source))
  File "/usr/lib64/python2.5/doctest.py", line 224, in _indent
    return re.sub('(?m)^(?!$)', indent*' ', s)
  File "/usr/lib64/python2.5/re.py", line 150, in sub
    return _compile(pattern, 0).sub(repl, string, count)
  File "/usr/lib64/python2.5/re.py", line 239, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib64/python2.5/sre_compile.py", line 507, in compile
    p = sre_parse.parse(p, flags)
AttributeError: 'NoneType' object has no attribute 'parse'



Error in test BaseShortUrlHandler (ao.shorturl)
Traceback (most recent call last):
  File "/usr/lib64/python2.5/unittest.py", line 260, in run
    testMethod()
  File "/usr/lib64/python2.5/doctest.py", line 2123, in runTest
    test, out=new.write, clear_globs=False)
  File "/usr/lib64/python2.5/doctest.py", line 1351, in run
    self.debugger = _OutputRedirectingPdb(save_stdout)
  File "/usr/lib64/python2.5/doctest.py", line 324, in __init__
    pdb.Pdb.__init__(self, stdout=out)
  File "/usr/lib64/python2.5/pdb.py", line 57, in __init__
    cmd.Cmd.__init__(self, completekey, stdin, stdout)
  File "/usr/lib64/python2.5/cmd.py", line 90, in __init__
    import sys
  File "<doctest shorturl.txt[10]>", line 4, in fakeimport
NameError: global name 'realimport' is not defined

但是,当我从python交互式控制台运行相同的代码时,它 确实 起作用。

更多编辑:

我正在使用zope.testing一个测试文件shorturl.txt该文件具有特定于我模块这一部分的所有测试。首先,我导入zope.component可用的模块,以演示和测试常用用法。缺少zope.*软件包被认为是一种极端情况,因此我稍后将对其进行测试。因此,reload()zope.*无法使用之后,我必须以某种方式进入我的模块。

到目前为止,我什至尝试在tempdir中使用tempfile.mktempdir()and
emptyzope/__init__.pyzope/component/__init__.pyfiles,然后将tempdir插入sys.path[0],并zope.*从中删除旧包sys.modules

也没用。

甚至更多编辑:

在此期间,我已经尝试过:

>>> class NoZope(object):
...     def find_module(self, fullname, path):
...         if fullname.startswith('zope'):
...             raise ImportError
...

>>> import sys
>>> sys.path.insert(0, NoZope())

而且它对于测试套件的名称空间(=对于中的所有导入shorturl.txt)都适用,但是在我的主模块中未执行ao.shorturl。即使是我reload()也没有。知道为什么吗?

>>> import zope  # ok, this raises an ImportError
>>> reload(ao.shorturl)    <module ...>

导入zope.interfaces会引发一个ImportError,因此它不会到达我导入的部分zope.component,并且
保留在ao.shorturl命名空间中 。为什么?!

>>> ao.shorturl.zope.component  # why?! 
<module ...>

问题答案:

只需将猴子补丁html" target="_blank">添加到builtins您自己的版本中,__import__当它意识到要在其上模拟错误的特定模块上正在调用它时,它可以引发您想要的任何事情。有关详细信息,请参阅文档。大致:

try:
    import builtins
except ImportError:
    import __builtin__ as builtins
realimport = builtins.__import__

def myimport(name, globals, locals, fromlist, level):
    if ...:
        raise ImportError
    return realimport(name, globals, locals, fromlist, level)

builtins.__import__ = myimport

代替...,您可以硬编码name == 'zope.component'或使用自己的回调更灵活地安排事务,这可以使导入在不同情况下按需提高,具体取决于您的特定测试需求,而无需您编写多个__import__类似的函数;-)

还需要注意的是,如果你使用的是什么,而不是import zope.component或者from zope.component import something,是from zope import component时,name届时将'zope',并'component'随后将是唯一的项目fromlist

编辑 :该__import__函数的文档说要导入的名称是builtin(就像在Python
3中一样),但实际上您需要__builtins__-我已经编辑了上面的代码,因此无论哪种方式都可以。



 类似资料:
  • 问题内容: 我在Python中使用时遇到了一些困难: 测试实际上返回正确的值,但它是Mock对象,不是。您如何在Python库中模拟属性? 问题答案: 您需要使用和: 这意味着:调用时,在该调用的返回值上,为属性设置a以返回value 。

  • 我在python文件中有以下代码。我必须对这个文件进行单元测试。但是为了做到这一点,我需要实例化类的对象

  • 问题内容: 我正在开发一个Web应用程序,该应用程序显然在iOS设备中存在问题。问题是我不拥有iOS设备,而是在Linux Ubuntu中进行开发。我正在寻找一种在Linux(尤其是浏览器)中仿真/模拟此OS的方法,但是还没有找到任何东西。 到目前为止,我发现的是iOS SDK的Simulator,但这是针对Mac的。还有一些Windows模拟器。有人做过吗? 问题答案: 我能想到的唯一解决方案是

  • 问题内容: 我需要在Python程序中模拟循环。不幸的是,以下简单的代码不起作用: 代替“ 1,2,3,done”,它输出以下输出: 为了捕获“停止迭代”异常并正确中断while循环,我该怎么办? 为什么需要这种东西的一个示例在下面显示为伪代码。 状态机: 问题答案: 我不确定你要做什么。你可以像这样实现一个循环: 要么: 你在尝试使用do while循环来打印列表中的内容在做什么?为什么不使用:

  • 问题内容: Python 2有两个整数数据类型和,并在必要时自动在它们之间进行转换,尤其是为了避免整数溢出。 我正在Python中模拟C函数,并且想知道是否存在重新启用整数溢出的标准方法。对于随机数,我已经使用 有没有更标准的方式来做同样的事情? 问题答案: 我认为基本思路是合理的,但需要进行一些调整: 您的函数不会在上溢出,但是应该; 一次操作可以超过几次; 还需要考虑以下负值。 考虑到这一点,

  • 问题内容: 如何在python中模拟按键?我也想同时按下多个键。 就像是: 要么 问题答案: 尽管它特定于X,但是您可以安装xautomation软件包(在基于Debian的系统上)并用于模拟按键,例如: