在 MicroPython 中,如何从字符串中加载模块
Posted
技术标签:
【中文标题】在 MicroPython 中,如何从字符串中加载模块【英文标题】:In MicroPython how do I load a module from a string 【发布时间】:2021-11-08 05:01:26 【问题描述】:在基于 ESP32/MicroPython 的项目中,我想从 RAM(重新)加载模块,而不必先将它们写入基于闪存的文件系统。 (这既费时又消耗闪存)
所以我的想法是检索例如module.py
通过web,然后使用__import__
,exec()
等将其转换为实际模块。但我不知道怎么做。
其实我需要的和这个差不多:How to load a module from code in a string?
在 MicroPython 中没有 imp
或 importlib
甚至 types.ModuleType
模块,但至少你有 __import__
。
有没有办法实现
my_code = 'a = 5'
mymodule = imp.new_module('mymodule')
exec(my_code, mymodule.__dict__)
没有imp.new_module
?
我尝试使用sys.__class__('mymodule')
将模块类型从现有模块中偷运出来,但我得到了
>>> mymodule = sys.__class__('mymodule')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't create 'module' instances
【问题讨论】:
如果您只需要命名空间/.__dict__
,那么为什么不能只使用虚拟类而不是ModuleType
?
【参考方案1】:
我不知道这对您是否可行,但另一种方法可能是在 ram 中创建一个文件系统,将字符串复制到该文件系统,然后使用传统的 import 语句。
MicroPython reference 表示“文件系统也可以使用外部闪存、RAM 等”,以及“MicroPython 实现了类似 Unix 的虚拟文件系统 (VFS) 层”,以及 继续提供在 RAM 中实现简单块设备的代码:
class RAMBlockDev:
def __init__(self, block_size, num_blocks):
self.block_size = block_size
self.data = bytearray(block_size * num_blocks)
def readblocks(self, block_num, buf):
for i in range(len(buf)):
buf[i] = self.data[block_num * self.block_size + i]
def writeblocks(self, block_num, buf):
for i in range(len(buf)):
self.data[block_num * self.block_size + i] = buf[i]
def ioctl(self, op, arg):
if op == 4: # get number of blocks
return len(self.data) // self.block_size
if op == 5: # get block size
return self.block_size
您只需创建和挂载文件系统:
import os
bdev = RAMBlockDev(512, 50)
os.VfsFat.mkfs(bdev)
os.mount(bdev, '/ramdisk')
然后简单地使用它:
with open('/ramdisk/hello.txt', 'w') as f:
f.write('Hello world')
print(open('/ramdisk/hello.txt').read())
【讨论】:
这实际上是我现在正在做的事情——我希望有一些轻巧的旅行方式,但看起来这是节省闪存的方式。我想知道为什么 MicroPython 一直从头开始删除创建模块的所有方法。无论如何我希望这不是 the 最终答案,但我给你+1,因为它有效。如果没有好的方法,我将把它作为答案(我必须先重新提出我的问题:))以上是关于在 MicroPython 中,如何从字符串中加载模块的主要内容,如果未能解决你的问题,请参考以下文章