Python仅导入根模块后如何访问其内部嵌套子模块的成员
问题原因
Python导入父模块时不会自动递归加载所有子模块,只有当子模块被显式导入后,才会作为属性挂载到父模块对象上。你直接import OpenGL as gl时仅加载了OpenGL根模块,GL、GL.shaders等子模块都没有被加载,因此访问gl.GL会抛出属性不存在的错误。
实现方法
完全可以实现你要的仅导入根模块、用完整路径访问成员的需求,只需要在导入根模块后显式触发需要用到的子模块加载即可,修改导入部分的代码为:
import OpenGL as gl # 显式加载需要的子模块,加载后会自动挂载到gl对象的属性上 import OpenGL.GL import OpenGL.GL.shaders # 其他依赖导入保持不变 import pygame as pg import numpy as np import ctypes
之后你就可以直接用完整路径调用所有成员:
- 原来的
gl.glClearColor改成gl.GL.glClearColor - 原来的
gls.compileShader改成gl.GL.shaders.compileShader - 所有常量比如
GL_COLOR_BUFFER_BIT也改成gl.GL.GL_COLOR_BUFFER_BIT即可
修改后的完整可运行代码
import OpenGL as gl import OpenGL.GL import OpenGL.GL.shaders import pygame as pg import numpy as np import ctypes class App: def __init__(self): # 初始化pygame pg.init() pg.display.set_mode((640,480), pg.OPENGL|pg.DOUBLEBUF) self.clock = pg.time.Clock() # 初始化opengl gl.GL.glClearColor(0.1, 0.2, 0.2, 1) self.shader = self.createShader("shaders/vertex.txt", "shaders/fragment.txt") self.triangle = Triangle(self.shader) self.mainLoop() def createShader(self, vertexFilepath, fragmentFilepath): with open(vertexFilepath,'r') as f: vertex_src = f.readlines() with open(fragmentFilepath,'r') as f: fragment_src = f.readlines() shader = gl.GL.shaders.compileProgram( gl.GL.shaders.compileShader(vertex_src, gl.GL.GL_VERTEX_SHADER), gl.GL.shaders.compileShader(fragment_src, gl.GL.GL_FRAGMENT_SHADER) ) return shader def mainLoop(self): running = True while (running): # 检查事件 for event in pg.event.get(): if (event.type == pg.QUIT): running = False # 刷新屏幕 gl.GL.glClear(gl.GL.GL_COLOR_BUFFER_BIT) self.triangle.draw(self.shader) pg.display.flip() # 计时 self.clock.tick() framerate = int(self.clock.get_fps()) pg.display.set_caption(f"Running at {framerate} fps.") self.quit() def quit(self): self.triangle.destroy() gl.GL.glDeleteProgram(self.shader) pg.quit() class Triangle: def __init__(self, shader): gl.GL.glUseProgram(shader) # x, y, z, r, g, b self.vertices = ( -0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 1.0 ) self.vertices = np.array(self.vertices, dtype=np.float32) self.vertex_count = 3 self.vao = gl.GL.glGenVertexArrays(1) gl.GL.glBindVertexArray(self.vao) self.vbo = gl.GL.glGenBuffers(1) gl.GL.glBindBuffer(gl.GL.GL_ARRAY_BUFFER, self.vbo) gl.GL.glBufferData(gl.GL.GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, gl.GL.GL_STATIC_DRAW) gl.GL.glEnableVertexAttribArray(0) gl.GL.glVertexAttribPointer(0, 3, gl.GL.GL_FLOAT, gl.GL.GL_FALSE, 24, ctypes.c_void_p(0)) gl.GL.glEnableVertexAttribArray(1) gl.GL.glVertexAttribPointer(1, 3, gl.GL.GL_FLOAT, gl.GL.GL_FALSE, 24, ctypes.c_void_p(12)) def draw(self, shader): gl.GL.glUseProgram(shader) gl.GL.glBindVertexArray(self.vao) gl.GL.glDrawArrays(gl.GL.GL_TRIANGLES, 0, self.vertex_count) def destroy(self): gl.GL.glDeleteVertexArrays(1,(self.vao,)) gl.GL.glDeleteBuffers(1,(self.vbo,)) if __name__ == "__main__": app = App()
内容的提问来源于stack exchange,提问作者Angelo Azevedo
相关产品推荐
相关产品推荐

