如何使用Python多处理为pygame准备图像 [英] How to use Python multiprocessing to prepare images for pygame

查看:142
本文介绍了如何使用Python多处理为pygame准备图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一种幻灯片应用程序,它具有平移和缩放效果.我正在使用pygame.

I'm making a slideshow app with that oh-so-naught-ies pan and zoom effect. I'm using pygame.

因此,主显示为实时30fps +,我不希望它在需要加载新图像时出现卡顿现象-这花费了超过1/30秒的时间.

The main display is therefore realtime 30fps+, and I don't want it stuttering when it has to load a new image - this takes it over 1/30th of a second.

因此,我想使用一些并行过程来准备图像,并使用这些对象(这些类是类的实例)来向主过程提供信息.

So I wanted to use some parallel process to prepare the images and feed the main process with these objects, which are instances of a class.

我尝试使用线程和多进程.线程化有效",但仍然很容易(我责怪

I've tried with threading and with multiprocess. Threading 'works' but it's still jumpy (I blame python) - the whole thing slows down when the thread is busy! So the code ran but it didn't meet the goal of allowing a continually smooth display.

但是,一旦我从主进程接收到的已准备好的图像上调用一个方法,就会多进程出现段错误(pygame parachute).我已经尝试过管道和队列通信-都导致相同的问题.该方法将运行直到调用

But multiprocess segfaults (pygame parachute) as soon as I call a method on the received prepared image from the main process. I've tried pipe and queue communications - both result in the same problem. The method runs up until it does a call to

sized = pygame.transform.scale(self.image, newsize )

然后是段错误.此类与主进程没有任何依赖关系.

Then there's the segfault. This class does not have any dependencies from the main process.

Pygame是否不像多处理?还有另一种兼容的方式吗?有没有一种方法可以使二级线程变好",从而可能停止线程化方法的执行?

Does pygame just not like multiprocessing? Is there another way that is compatible? Is there a way to 'nice' secondary threads that might stop the threading method performing?

任何帮助,我们将不胜感激.很乐意发布更多代码,只是在评论中提问,但除非有必要,否则不想在此处转储大清单.

Any help greatly appreciated. Happy to post more code, just ask in comments, but didn't want to dump a big listing here unless needed.

提前谢谢!

这是我能做到的. 您需要在底部的构造函数中提供三个指向jpeg文件的路径.

#!/usr/bin/env python2
import pygame
import sys
import time
import re
import os
import pickle
from random import randrange, shuffle
from multiprocessing import Process, Pipe
import Queue


class Img:
    """The image objects I need to pass around"""
    def __init__(self, filename=None):
        image = pygame.image.load(filename).convert()
        self.image = pygame.transform.scale(image, (640,480))

    def getSurface(self):
        """Get a surface, blit our image onto it in right place."""
        surface = pygame.Surface((640,480))
        # xxx this next command fails
        sized = pygame.transform.scale(self.image, (640,480))
        surface.blit(sized, (0,0))
        return surface

class Floaty:
    """demo"""
    def __init__(self, fileList):
        self.fileList = fileList
        pygame.init()
        self.screen = pygame.display.set_mode((640,480))

        # open the first image to get it going
        self.img = Img(self.fileList.pop())

        # Set up parallel process for opening images
        self.parent_conn, child_conn = Pipe()
        self.feeder = Process(target=asyncPrep, args=(child_conn,))
        self.feeder.start()

    def draw(self):
        """draw the image"""
        # collect image ready-prepared by other process
        if self.parent_conn.poll():
            self.img = self.parent_conn.recv()
            print ("received ", self.img)

        # request new image
        self.parent_conn.send(self.fileList.pop())

        self.screen.blit(self.img.getSurface(), (0, 0))
        pygame.display.flip()

def asyncPrep(conn):
    """load up the files"""

    while True:
        if conn.poll(1):
            filename = conn.recv()
            print ("doing ", filename)
            img = Img(filename)
            conn.send(img)


if __name__ == '__main__':
    fileList = ['/path/to/a.jpg', 'path/to/b.jpg', 'path/to/c.jpg']
    f = Floaty(fileList)
    clock = pygame.time.Clock()
    while 1:
        f.draw()
        clock.tick(4);

运行此命令(Python 2.7.6)时,我得到:

When I run this (Python 2.7.6) I get:

('doing ', '/path/to/a.jpg')
('received ', <__main__.Img instance at 0x7f2dbde2ce60>)
('doing ', '/path/to/b.jpg')
Fatal Python error: (pygame parachute) Segmentation Fault
zsh: abort (core dumped)

推荐答案

我使用多重处理解决了这一问题,方法是使Img类将图像加载到存储在属性中的字符串缓冲区中,然后添加一个postReceive方法来加载它进入存储在image属性中的表面.

I solved this using multiprocessing by making the Img class load the image into a string buffer, stored in a property, then adding a postReceive method which loads it into a surface stored in the image property.

从子级接收到Img对象后,父进程将调用postReceive方法.

The postReceive method is called by the parent process after receiving the Img object from the child.

因此,孩子创建的对象未绑定到任何pygame-y.

Therefore the object created by the child is not bound to anything pygame-y.

    self.imageBuffer = pygame.image.tostring(
      pygame.transform.scale(image, (640,480)),
      'RGB')

然后,Img中的新方法很简单:

Then, the new method in Img is simply:

def: postReceive(self):
    self.image = pygame.image.frombuffer( self.imagebuffer, 'RGB' )

在此处添加呼叫:

    # collect image ready-prepared by other process
    if self.parent_conn.poll():
        self.img = self.parent_conn.recv().postReceive()
        print ("received ", self.img)

这篇关于如何使用Python多处理为pygame准备图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆