big*_*ose 6 python unit-testing
Python程序如何从具有任意名称的文件轻松导入Python模块?
标准库导入机制似乎没有帮助.一个重要的限制是我不希望出现附带的字节码文件 ; 如果我imp.load_module在一个名为的源文件上使用foo,fooc则会出现一个名为的文件,这是一个混乱和混乱.
Python导入机制期望它最好地知道文件名是什么:模块文件位于特定的文件系统位置,特别是文件名具有特定的后缀(foo.py对于Python源代码等)而没有其他文件系统位置.
这与另一个约定冲突,至少在Unix上:将作为命令执行的文件应该在不引用实现语言的情况下进行命名.例如,执行"foo"的命令应该在名为foono suffix 的程序文件中.
但是,对这样的程序文件进行单元测试需要导入该文件.我需要程序文件中的对象作为Python模块对象,准备在单元测试用例中进行操作,就像import我给出的那样.
导入模块的Pythonic方法是什么,特别是从名称不以文件结尾的文件.py,没有出现该导入的字节码文件?
import os
import imp
py_source_open_mode = "U"
py_source_description = (".py", py_source_open_mode, imp.PY_SOURCE)
module_filepath = "foo/bar/baz"
module_name = os.path.basename(module_filepath)
with open(module_filepath, py_source_open_mode) as module_file:
foo_module = imp.load_module(
module_name, module_file, module_filepath, py_source_description)
Run Code Online (Sandbox Code Playgroud)
到目前为止,我最好的实现是(仅使用 Python 2.6 或更高版本中的功能):
import os
import sys
import imp
import contextlib
@contextlib.contextmanager
def preserve_value(namespace, name):
""" A context manager to preserve, then restore, the specified binding.
:param namespace: The namespace object (e.g. a class or dict)
containing the name binding.
:param name: The name of the binding to be preserved.
:yield: None.
When the context manager is entered, the current value bound to
`name` in `namespace` is saved. When the context manager is
exited, the binding is re-established to the saved value.
"""
saved_value = getattr(namespace, name)
yield
setattr(namespace, name, saved_value)
def make_module_from_file(module_name, module_filepath):
""" Make a new module object from the source code in specified file.
:param module_name: The name of the resulting module object.
:param module_filepath: The filesystem path to open for
reading the module's Python source.
:return: The module object.
The Python import mechanism is not used. No cached bytecode
file is created, and no entry is placed in `sys.modules`.
"""
py_source_open_mode = 'U'
py_source_description = (".py", py_source_open_mode, imp.PY_SOURCE)
with open(module_filepath, py_source_open_mode) as module_file:
with preserve_value(sys, 'dont_write_bytecode'):
sys.dont_write_bytecode = True
module = imp.load_module(
module_name, module_file, module_filepath,
py_source_description)
return module
def import_program_as_module(program_filepath):
""" Import module from program file `program_filepath`.
:param program_filepath: The full filesystem path to the program.
This name will be used for both the source file to read, and
the resulting module name.
:return: The module object.
A program file has an arbitrary name; it is not suitable to
create a corresponding bytecode file alongside. So the creation
of bytecode is suppressed during the import.
The module object will also be added to `sys.modules`.
"""
module_name = os.path.basename(program_filepath)
module = make_module_from_file(module_name, program_filename)
sys.modules[module_name] = module
return module
Run Code Online (Sandbox Code Playgroud)
这有点太宽泛了:它在模块的整个导入过程中禁用字节码文件生成,这意味着在该过程中导入的其他模块也不会生成字节码文件。
我仍在寻找一种方法来仅为指定的模块文件禁用字节码文件生成。
| 归档时间: |
|
| 查看次数: |
1768 次 |
| 最近记录: |