封装导入模块的范围

鲍比

在项目中使用可怕的RoboClaw Python“库”,我似乎无法克服这样一个事实,即它们抛出了许多函数和全局变量,这些函数和全局变量用于处理与物理硬件的接口到文件中。不幸的是,我一直在使用该库,因为当供应商为其开发板发布新固件时,他们也在网站上更新了该文件。将其移植到有用的东西将是不断的努力。

当我尝试多次导入该问题时,对于连接到USB的每个板一次,都会出现此问题。这样的(从概念上来说)将是理想的:

import roboclaw
class Board:
    def __init__(self):
        self.rc = roboclaw

由于Python解释器似乎在每次导入时都在内存中维护相同的模块引用,因此我似乎无法获得它来创建存在于单独命名空间中的实例,从而在所有板卡不正确地变成所有类型的I / O冲突错误时会吐出来分配给相同的/dev/ttyACM设备文件。我似乎能够获得的最接近的答案是Noctis Skytower提供的答案,但它仍然没有为每个Board实例创建单独的命名空间

此外,尽管它们都无法导入,因为它们找不到位于同一目录中文件,我尝试使用imp(像这样)和importlib(像这样设置动态导入roboclaw.py

我应该继续前进的方向有点茫然,因为我以前从未处理过。

塔德·麦当劳·詹森

好吧,通常我会像我建议的那样谴责黑客,但是似乎您没有太多选择,因为该软件包的作者显然不了解面向对象编程的含义,因此有一种创建函数副本的方法通过直接调用FunctionType()构造函数来改变全局范围

from types import FunctionType
from functools import wraps

def copy_func(func,global_namespace):
    "copies a function object with the new specified global scope"
    c = FunctionType(func.__code__,global_namespace,func.__name__,func.__defaults__,func.__closure__)
    try:
        c.__kwdefaults__ = func.__kwdefaults__
    except AttributeError:pass #this is only for python 3
    c = wraps(func)(c) #copy all metadata although there doesn't seem to be any for roboclaw
    return c

这样,它根本不影响模块中的功能,但仍使用您自己的名称空间,然后可以使用以下方法欺骗复制模块:

class CopyScope:
    def __init__(self,module):
        own_scope = self.__dict__
        for name,thing in vars(module).items():
            if isinstance(thing,FunctionType):
                setattr(self, name, copy_func(thing, own_scope))
            else:
                setattr(self, name, thing)
                #you could also do own_scope[name] = .. instead of setattr() but I prefer setattr()

尽管这仅copy_func适用于所有模块级别的功能,而不适用于可能使用全局语句的任何方法,但我可以想象,如果作者了解什么方法,则根本不需要此方法。

我可以使用以下代码进行测试:

import roboclaw
x = CopyScope(roboclaw)

x.crc_clear()
x.crc_update(4)

print(x._crc)
print(roboclaw._crc) #this will actually raise an error because it isn't defined in the original module yet.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章