【问题标题】:Python/Wand image.save() hangs if called several times如果多次调用 Python/Wand image.save() 会挂起
【发布时间】:2020-06-15 03:09:02
【问题描述】:

使用 Python 代码读取周期性更改文件的内容(MP3 上的信息),并使用 Wand 根据手头的信息创建特定的动画 gif。然而,我遇到了一个严重的问题,即 gif 在几次通过后拒绝保存;在两到三遍之后,image.save() 要么无限运行,要么处理时间急剧增加。我看不出有什么突然变化的原因。

这里的代码是一个测试用例,用于验证问题不在于文件读取,事实并非如此。

# coding=latin-1

from wand.image import Image        # ImageMagick
from wand.font import Font          # IM Font Handler
from wand.drawing import Drawing    # IM Drawing API
from wand.color import Color        # IM Colour definitions
from watchdog.observers import Observer             # Event monitors
from watchdog.events import FileSystemEventHandler  # Event handlers

import time                         # for the stopwatch
import sys, os

FONT_NAME =  'c://windows//fonts//alarm clock.ttf';
FONT_SIZE = 80;
SPACING = 1;

def ImageMaker(title, album, composer, playtime):
    print("DEBUG: Entering ImageMaker()");
    start = time.time();

    title = title.ljust(60,' '); # these strings are space-padded to work properly in draw.text()
    album = album.ljust(60,' ');
    composer = composer.ljust(60,' ');
    details = [title, album, composer];

    counter = 0;
    frame_counter = 0;

    bg = Image(filename="nowplaying_background.png");   # this is a static, pre-generated file
    gif = Image(background=Color('rgb(0,0,0)'), height=200, width=1440);

    if (int(playtime) > 45):    # the script takes so long, very short MP3s finish before the script does
        for x in details:
            while (counter <= len(x)+1 and counter < 30 and len(x) != 0):
                with Image(height=200, width=1440, depth=8) as img:
                    with Drawing() as draw:
                        draw.font = FONT_NAME;
                        draw.font_size = FONT_SIZE;
                        draw.text_interline_spacing = SPACING;
                        draw.fill_color = Color('rgb(255, 194, 0)');
                        draw.stroke_width = 0;
                        a = x[(29-counter):30];     # start at 30, step back to 0
                        b = x[59-counter:len(x)];   # start at 60, step back to 30
                        draw.text(20, 65, a);   # top line text
                        draw.text(20, 130, b);  # bottom line text
                        draw(img);
                    with Image(height=200, width=1440) as final:
                        final.composite(bg);        # draw static bg on the image context
                        final.composite(img);       # draw the current fg over the bg
                        if(frame_counter > 0):
                            gif.sequence.append(final);
                        else:
                            gif.sequence[0] = final;
                        final.clear();
                        gif.sequence[frame_counter].delay = 30;
                        img.clear();
                counter += 1; 
                frame_counter += 1;
            counter = 0;
            print("DEBUG: Exiting frame generator");
        gif.sequence[29].delay = 200;       # these set the delays between the three elements longer
        gif.sequence[59].delay = 200;       # so they're more readable
        gif.sequence[89].delay = 200;
        gif.type = 'optimize';              
        gif.save(filename="c://users/magni/desktop/nowplaying.gif");
        gif.destroy();
        bg.destroy();
    else:
        print("DEBUG: Skipping image generation, song is too short");

    end = time.time();
    elapsed = end - start;
    print("Time to completition: ", elapsed);

# These are simulated samples
ImageMaker("ABCDEF", "GHIJKLMNO", "QRSTUVWXYZ", "60");
ImageMaker("ABCDEF", "GHIJKLMNO", "QRSTUVWXYZ", "60");
ImageMaker("QRSTUVWXYZ", "ABCDEF", "GHIJKLMNO", "90");
ImageMaker("QRSTUVWXYZ", "ABCDEF", "GHIJKLMNO", "90");
ImageMaker("American Meeting", "Teitoku no Ketsudan 2", "Yoichiro Yoshikawa", "133");
ImageMaker("American Meeting", "Teitoku no Ketsudan 2", "Yoichiro Yoshikawa", "133");

示例输出:

DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  22.29582381248474
DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  23.027299642562866
DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  21.273354291915894
DEBUG: Entering ImageMaker() on a modified file
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
Time to completition:  139.14677023887634
DEBUG: Entering ImageMaker()
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator
DEBUG: Exiting frame generator

十五分钟后,第五个循环还没有结束,被手动终止。目标文件 (nowplaying.gif) 在此期间继续增长,当进程被终止时,其大小接近 2 兆字节。最后的 gif 被破坏了,这是有道理的,因为它没有完全保存。

我不确定我是否做错了什么,或者我偶然发现了 Wand 实现中的错误(版本 0.6.1,最新可用)。我的 Python 技能不是特别好,但我仔细阅读了错误报告和文档,但在这个特定问题上我一无所获。

【问题讨论】:

    标签: python python-3.x imagemagick wand


    【解决方案1】:

    问题似乎与过时的 Wand 版本有关;正在使用的 python 解释器运行的是 0.5.8,而不是 0.6.1(我有两个 python 安装,并且用 pip 引用了错误的一个)。更新到 0.6.1 解决了这个问题,可能是内存引用重写的一部分。

    考虑到这个问题已回答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2020-06-29
      • 1970-01-01
      • 2018-08-09
      • 2016-02-03
      • 1970-01-01
      相关资源
      最近更新 更多