简体   繁体   English

封装导入模块的范围

[英]Encapsulate the scope of an imported module

Using the hideous RoboClaw Python "library" in a project, I can't seem to get past the fact that they threw a bunch of functions and global variables that deal with interfacing with physical hardware into a file. 在项目中使用可怕的RoboClaw Python“库” ,我似乎无法摆脱这样一个事实:它们抛出了许多函数和全局变量,这些函数和全局变量用于处理与物理硬件的接口到文件中。 Unfortunately, I am stuck using this library because when the vendor releases a new firmware for their board, they also update this file on their website; 不幸的是,我一直在使用该库,因为当供应商为他们的主板发布新固件时,他们也在网站上更新了该文件。 porting it to something useful would be a continuous effort. 将其移植到有用的东西将是不断的努力。

The issue arises when I attempt to import it multiple times, once for each board that I have attached to USB. 当我尝试多次导入该问题时,对于连接到USB的每个板一次,都会出现此问题。 Something (conceptually) like this would be ideal: 像这样(从概念上)是理想的:

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

Since the Python interpreter seems to maintain the same module reference in memory with every import, I can't seem to get it to create instances that exist in separate namespaces, essentially spitting out all kinds of I/O conflict errors when all boards incorrectly become assigned to the same /dev/ttyACM device file. 由于Python解释器似乎在每次导入时都在内存中维护相同的模块引用,因此我似乎无法获得创建在单独命名空间中存在的实例的方法,从而在所有板卡错误地变成所有类型的I / O冲突错误时就吐出来了。分配给相同的/dev/ttyACM设备文件。 The closest that I seem to be able to get is this answer provided by Noctis Skytower , but it still isn't creating a separate namespaces for each Board instance. 我似乎能够获得的最接近的答案是Noctis Skytower提供的答案 ,但是它仍然没有为每个Board实例创建单独的命名空间。

Additionally, I have tried setting up dynamic imports using imp (like this ) and importlib (like this ) though both of these fail to import because they can't find the roboclaw.py file that sits in the same directory. 此外,我已经尝试设置使用动态进口imp (像这样 )和importlib (像这样 ),虽然这两个导入失败,因为他们无法找到roboclaw.py在同一个目录中坐在文件。

At a bit of a loss for the direction that I should be going on this, as I've never had to deal with this before. 我应该继续前进的方向有点茫然,因为我以前从未处理过。

Ok normally I would condemn hacks like the one I am suggesting but it seems you don't have much choice as the author of that package clearly did not understand the meaning of object oriented programming , there is a way to create a copy of a function with a different global scope by directly calling the FunctionType() contructor: 好的,通常我会像我建议的那样谴责黑客,但是似乎您没有太多选择,因为该软件包的作者显然不了解面向对象编程的含义,因此有一种创建函数副本的方法通过直接调用FunctionType()构造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

This way it does not affect the functions in the module at all but still uses your own namespace, you can then spoof a copy module with this: 这样,它根本不影响模块中的功能,但仍使用您自己的名称空间,然后您可以使用以下方法欺骗复制模块:

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()

Although this only runs copy_func for all the module level function and not any methods that may use the global statement but I'd imagine that if the author understood what methods were you wouldn't need this at all. 尽管这仅对所有模块级别的函数运行copy_func ,而不对可能使用全局语句的任何方法运行,但我可以想象,如果作者了解什么方法,则根本不需要此方法。

I was able to test this with the following code: 我可以使用以下代码进行测试:

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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM