2016-04-10 97 views
2

TL; DR导入,Python的2.7

对于固定的和不可改变的非封装的目录结构是这样的:

some_dir/ 
    mod.py 
    test/ 
     test_mod.py 
     example_data.txt 

什么是一个非-package方式使test_mod.pymod.py导入?

我被限制在这种情况下使用Python 2.7。

我想为mod.py中的函数写一些测试。我想创建一个新目录test,它与mod.py并排,并且里面有一个测试文件test/test_mod.py,它应该从mod.py导入功能并测试它们。

由于相对导入的众所周知的局限性,它依赖于基于包的命名,所以不能以直接的方式完成此操作。然而,关于该主题的所有建议都建议将该脚本构建为一个包,然后使用相对导入,这对我的用例来说是不可能的。

在我的情况下,mod.py不可以作为一个包来构建,我不能要求mod.py的用户来安装它。他们可以自由地仅仅从版本控制中检查文件,然后开始使用它,但是他们希望,并且我无法改变这种情况。

鉴于此,有什么方法可以提供简单,直接的test目录

注:只是坐在旁边mod.py测试文件,但实际测试的目录,因为会有其他资产一样,随之而来的测试数据,和子目录组织是至关重要的。

我很抱歉如果这是重复的,但是在发布之前我在研究中看到的这个问题的十几个排列中,我还没有看到一个解决如何执行此操作的问题。他们都说要使用包装,这对我的情况来说不是一个允许的选择。

+0

也许不是最优雅的解决方案,但您可以为您的测试跑步者修改'PYTHONPATH'。 。 。 – mgilson

回答

1

根据@mgilson的评论,我在测试目录中添加了一个文件import_helper.py

some_dir/ 
    mod.py 
    test/ 
     test_mod.py 
     import_helper.py 
     example_data.txt 

这里是import_helper.py内容:

import sys as _sys 
import os.path as _ospath 
import inspect as _inspect 
from contextlib import contextmanager as _contextmanager 

@_contextmanager 
def enable_parent_import(): 
    path_appended = False 
    try: 
     current_file  = _inspect.getfile(_inspect.currentframe()) 
     current_directory = _ospath.dirname(_ospath.abspath(current_file)) 
     parent_directory = _ospath.dirname(current_directory) 
     _sys.path.insert(0, parent_directory) 
     path_appended = True 
     yield 
    finally: 
     if path_appended: 
      _sys.path.pop(0) 

然后在test_mod.py进口部分,之前试图导入mod.py来,我说:

import unittest 
from import_helper import enable_parent_import 

with enable_parent_import(): 
    from mod import some_mod_function_to_test 

它不幸的是需要手动修改PYTHONPATH,但是将其作为上下文管理器写一点会有所帮助,并将其恢复到其o父目录修改之前的严格状态。

为了让这个解决方案能够跨越这个问题的多个实例(比如明天我要求为一些不相关的任务编写一个widget.py模块,并且它也不能作为包分发),我必须复制我的帮助函数并确保它的副本随测试分发,或者我必须将该小工具编写为一个包,确保它在全球范围内安装在我的用户群中,然后继续向前发展。

当您管理公司内部的很多Python代码时,通常会出现一种不正常的代码分布模式,即“安装”某些Python代码变得相当于从版本控制中检出新版本。

由于代码通常非常集中且特定于较小团队的一小部分子任务的一小部分任务,所以维持通过打包共享代码的开销(即使它通常是一个更好的主意)将永远不会发生。因此,我觉得我上面描述的用例对于真实世界的Python非常常见,如果某些导入工具添加了此功能来修改PYTHONPATH,那么这将很不错,目录)非常容易。

这样你就可以依靠这个至少成为标准库的一部分,而不需要推出你自己的代码,并确保它随测试一起提供或安装在你的用户基础上。