You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 18:36:05