Python 封装导入模块的作用域

Python 封装导入模块的作用域,python,class,namespaces,instance,Python,Class,Namespaces,Instance,在一个项目中使用,我似乎无法忽略这样一个事实,即他们将处理与物理硬件接口的一系列函数和全局变量放入一个文件中。不幸的是,我一直在使用这个库,因为当供应商为他们的主板发布新固件时,他们也会在他们的网站上更新这个文件;将其移植到有用的东西将是一项持续的工作 当我多次尝试导入它时,就会出现问题,对于我连接到USB的每个板都导入一次。这样的东西(概念上)是理想的: import roboclaw class Board: def __init__(self): self.rc =

在一个项目中使用,我似乎无法忽略这样一个事实,即他们将处理与物理硬件接口的一系列函数和全局变量放入一个文件中。不幸的是,我一直在使用这个库,因为当供应商为他们的主板发布新固件时,他们也会在他们的网站上更新这个文件;将其移植到有用的东西将是一项持续的工作

当我多次尝试导入它时,就会出现问题,对于我连接到USB的每个板都导入一次。这样的东西(概念上)是理想的:

import roboclaw
class Board:
    def __init__(self):
        self.rc = roboclaw
由于Python解释器似乎在每次导入时都在内存中维护相同的模块引用,因此我似乎无法让它创建存在于不同名称空间中的实例,当所有板错误地分配到相同的
/dev/ttyACM
设备文件时,实际上会抛出各种I/O冲突错误。我似乎能够得到的最接近的名称是,但它仍然没有为每个
实例创建单独的名称空间

此外,我还尝试使用
imp
(like)和
importlib
(like)设置动态导入,尽管这两种方法都无法导入,因为它们找不到位于同一目录中的
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.

哦,上帝,那太可怕了!我找到了一种覆盖全局名称空间的方法,所以我将在稍后发布一个可能的解决方案。谢谢!我相信这是可行的,至少我从IPython那里知道了。但是,当我执行这个应用程序时,我从pyserial中得到了一些错误。一旦我能确认这些是不相关的,我会将其标记为已解决。哦,一些错误,不是相同的错误。好的,我现在将停止更改添加项。