在运行时通过字符串从 python 访问模块和模块变量

在我的 Python 程序中,我想通过将字符串参数转换为变量名来动态加载模块和访问模块的变量。

用例

我在 SD 卡上有不同的字体,它们是 python 文件,还有一个显示功能,可以在需要显示字符时加载字体。

我的字体文件示例:

# arial14.py
# ch_(ASCII) = (widht), (height), [bitmask]
ch_33 = 3, 16, [0,0,0,0,0,0,0,0,0,1,1,1,1,1 ........
ch_34 = 5, 16, [0,0,0,0,0,0,0,0,0,0,0,0,0,0 ........
....

# arial20.py
ch_33 = 4, 22, [0,0,0,0,0,0,0,0,0,1,1,1,1,1 ........
ch_34 = 8, 22, [0,0,0,0,0,0,0,0,0,0,0,0,0,0 ........

此外,还有一个 Writer 类可以将字体呈现到显示器上:

class Writer(object):
    def __init__(self):
       try:
           global arial14
           import arial14
           self.current_module = "arial14"
           self.imported_fonts = []
           self.imported_fonds.append(self.current_module)
      except ImportError:
           print("Error loading Font")
   def setfont(self, fontname, fontsize):
           modname = fontname+str(fontsize)
           if modname not in self.importedfonts:
               try:
                    exec("global" + modname)
                    exec("import" + modname)      #import the font (works)
                    self.importedfonts.append(modname)
               except ImportError:
                    print("Error loading Font")
                    return
           else:
               print(modname+" was already imported")
           self.current_module = modname
           print("Font is set now to: "+ self.current_module

## HERE COMES THE NON WORKING PART:
    def putc_ascii(self, ch, xpos, ypos):

           execline = "width, height, bitmap = "+ self.cur_mod+".ch_"+str(ch)
           print(execline) 
           #this example.: width, height,bitmap = arial14.ch_55


           width, height,bitmap = arial14.ch_32
           print(width, height, bitmap) # values of arial14.ch_32 -> correct

           exec (execline)
           print(width, height, bitmap) # values of arial14.ch_32
                                        # BUT VALUES OF arial14.ch_55 EXPECTED

有没有人知道如何将正确字体的查询字符的正确值保存到变量宽度、高度和位图中?

我只想在需要时动态加载字体,并通过将新的 .py 字体文件放入文件夹来提供添加新字体的可能性。

提前致谢。

布鲁诺·德舒利耶

编辑

OP实际上使用的是micropython,它没有实现importlib ...

可能的(未经测试的)解决方案(是的,使用exec- 如果有人知道更好的解决方案,请加入)。

def import_module(name):
    name = name.strip().split(
    statement = "import {}"
    exec(statement, globals()) 
    return sys.modules[name]


class Writer(object):
    def __init__(self):
       # reference to the current module
       # WARNING : this is the `module` object itself, 
       # not it's name       
       self.current_module = None

       # {name:module} mapping
       # not sure it's still useful since we
       # now have a reference to the module itself
       # and `sys.modules` already caches imported 
       # modules... 
       self.imported_fonts = {}

       # set default font
       self.setfont("arial", "14")

    def setfont(self, fontname, fontsize):
        self.current_module = self._loadfont(fontname, fontsize)

    def _loadfont(self, fontname, fontsize):
        name = fontname+str(fontsize)
        if name not in self.imported_fonts:
            self.imported_fonts[name] = load_module(name)
        return self.imported_font[name]

    def putc_ascii(self, ch, xpos, ypos):
        width, height, bitmap = self._get_char(ch)
        print("{}.{}: {} - {} - {}".format(
            self.current_module, ch, width, height, bitmap
            )

    def _get_char(self, chrnum):
        # assume the font modules have been rewritten
        # using dicts (cf lower) and all chars are defined
        # in all fonts modules
        return self.current_module[ch]

        # alternate implementation using the current
        # fonts definitions
        # return getattr(self.current_module, "ch_{}".format(ch)) 

电话:DR

你想要importlib.import_module,最终getattr()但是你仍然应该阅读更长的答案,真的,它会为你节省很多时间和挫折。

更长的答案

关于“字体”文件格式的第一点 - 这个:

ch_33 = 3, 16, [0,0,0,0,0,0,0,0,0,1,1,1,1,1 ........
ch_34 = 5, 16, [0,0,0,0,0,0,0,0,0,0,0,0,0,0 ........

是一种巨大的设计气味。你想要列表或字典(或者可能是有序的字典),即:

characters = {
    33: (3, 16,  [0,0,0,0,0,0,0,0,0,1,1,1,1,1...]),
    34: (5, 16,  [0,0,0,0,0,0,0,0,0,0,0,0,0,0...]),
    # etc
    }

作为一般规则,当您开始使用“var1”、“var2”、“var3”等模式时,您就知道您想要某种容器。

第二点 - 您的错误处理,即:

 try:
       global arial14
       import arial14
       self.current_module = "arial14"
       self.imported_fonts = []
       self.imported_fonds.append(self.current_module)
  except ImportError:
       print("Error loading Font")

比无用更糟糕,它实际上是有害的。首先是因为它不会在出现不可恢复错误的情况下停止程序执行(当发生完全错误的事情时,希望程序继续运行),然后因为它替换了您从错误消息中获得的所有非常有用的信息和带有无用的“发生错误”消息的回溯。

仅捕获您可以通过一种或另一种方式正确管理的异常,让其他所有内容传播(也许调用堆栈中的上层人员 - 通常在 UI 部分 - 可能能够正确处理它)。

第三点:不要使用全局变量。我的意思是:不要改变或重新绑定全局变量(只读(伪常量)全局变量当然是可以的)。这意味着您真的永远不必在代码中使用“global”关键字。

当您需要在一组函数之间共享状态时,请使用类,将状态存储为属性并使您的函数成为方法。这就是对象的用途(嗯,这不仅是存在的理由之一)。

编辑这部分对于完整的 Python 实现仍然是正确的,对于 micropython 可能仍然部分正确,除了在 micropython 中没有实现的部分(比如importlib- 我不知道还缺少什么)

最后:永远不要使用execnor eval你不需要它们,无论你想做什么,都有一个更好、更安全的特定解决方案。

在您的情况下,要通过名称导入模块,您有importlib.import_module,并通过您拥有的名称获取对象的属性getattr()(但如果您使用适当的容器,请参见第一点,您甚至不需要getattr这里)。

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

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

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

PyQt:在运行时转换模块字符串

来自分类Dev

在运行时将模块添加到python

来自分类Dev

在运行时从类的字符串名称访问值

来自分类Dev

Castle和NLog在运行时更改连接字符串

来自分类Dev

Castle和NLog在运行时更改连接字符串

来自分类Dev

如何在运行时使用持有其名称的字符串访问常量字符串?

来自分类Dev

python的if子字符串的运行时

来自分类Dev

我可以在运行时在活动的Python Shell中更改模块的属性吗?

来自分类Dev

Python:哪个导入模块在运行时调用我的函数

来自分类Dev

Python:哪个导入模块正在运行时调用我的函数

来自分类Dev

在运行时向Python模块添加属性,以供以后导入

来自分类Dev

我可以在运行时在活动的Python Shell中更改模块的属性吗?

来自分类Dev

使用连接字符串和精简程序时如何在运行时更改初始目录

来自分类Dev

在运行时编辑shell脚本和python脚本

来自分类Dev

在Python中访问模块/模块作用域中的变量

来自分类Dev

在Python中访问导入模块中的变量

来自分类Dev

在python中运行时变量访问

来自分类Dev

在python中运行时变量访问

来自分类Dev

EF Core和LINQ-如何在运行时使用字符串变量构建动态的Where子句?

来自分类Dev

在运行时导入模块

来自分类Dev

在运行时重新加载模块

来自分类Dev

在运行时导入模块

来自分类Dev

在PHP中运行时,Python脚本与os和glob模块跳了一行

来自分类Dev

使用字符串变量访问JavaScript模块方法

来自分类Dev

在Python中,如何在循环中在文件中写入字符串,并且在循环停止之前,我可以在运行时获得结果?

来自分类Dev

是否可以在运行时找到方法,在 Kotlin 中传递变量或字符串名称,就像在 groovy 中一样

来自分类Dev

Python模块和全局变量

来自分类Dev

使用实体框架,依赖注入,工作单元和存储库模式在运行时注入/管理更改连接字符串

来自分类Dev

在运行时从对象的字符串名称创建具有泛型类型的类的实例和具有相同泛型类型的调用方法

Related 相关文章

  1. 1

    PyQt:在运行时转换模块字符串

  2. 2

    在运行时将模块添加到python

  3. 3

    在运行时从类的字符串名称访问值

  4. 4

    Castle和NLog在运行时更改连接字符串

  5. 5

    Castle和NLog在运行时更改连接字符串

  6. 6

    如何在运行时使用持有其名称的字符串访问常量字符串?

  7. 7

    python的if子字符串的运行时

  8. 8

    我可以在运行时在活动的Python Shell中更改模块的属性吗?

  9. 9

    Python:哪个导入模块在运行时调用我的函数

  10. 10

    Python:哪个导入模块正在运行时调用我的函数

  11. 11

    在运行时向Python模块添加属性,以供以后导入

  12. 12

    我可以在运行时在活动的Python Shell中更改模块的属性吗?

  13. 13

    使用连接字符串和精简程序时如何在运行时更改初始目录

  14. 14

    在运行时编辑shell脚本和python脚本

  15. 15

    在Python中访问模块/模块作用域中的变量

  16. 16

    在Python中访问导入模块中的变量

  17. 17

    在python中运行时变量访问

  18. 18

    在python中运行时变量访问

  19. 19

    EF Core和LINQ-如何在运行时使用字符串变量构建动态的Where子句?

  20. 20

    在运行时导入模块

  21. 21

    在运行时重新加载模块

  22. 22

    在运行时导入模块

  23. 23

    在PHP中运行时,Python脚本与os和glob模块跳了一行

  24. 24

    使用字符串变量访问JavaScript模块方法

  25. 25

    在Python中,如何在循环中在文件中写入字符串,并且在循环停止之前,我可以在运行时获得结果?

  26. 26

    是否可以在运行时找到方法,在 Kotlin 中传递变量或字符串名称,就像在 groovy 中一样

  27. 27

    Python模块和全局变量

  28. 28

    使用实体框架,依赖注入,工作单元和存储库模式在运行时注入/管理更改连接字符串

  29. 29

    在运行时从对象的字符串名称创建具有泛型类型的类的实例和具有相同泛型类型的调用方法

热门标签

归档