Django mod_wsgi 内存错误

7

在我的Django项目中遇到了MemoryError的奇怪问题。

  • Ubuntu 11
  • Apache2
  • Nginx
  • mod_wsgi
  • python2.7

我有一个使用PIL调整图像大小的模板标签,在我的开发机上运行得很好,但是在生产环境中,对于大图像(〜800px)会引起500错误。 模板标记似乎没有问题,但仅当原始图像已经非常小的情况下才有效。 模板标记是http://djangosnippets.org/snippets/1944/的修改版本

刚刚尝试了为python2.7重新编译mod_wsgi - 出现相同的错误。

是否有一种方法可以分配更多内存,或者可能还有其他我不理解的东西?

非常感谢任何帮助!

向我发送的跟踪邮件如下:

    Traceback (most recent call last):

     File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 111, in get_response
       response = callback(request, *callback_args, **callback_kwargs)

     File "/var/www/rizzyhome.com/www/django/rizzyhome/products/views.py", line 31, in designs
       context_instance=RequestContext(request)

     File "/usr/local/lib/python2.7/dist-packages/django/shortcuts/__init__.py", line 20, in render_to_response
       return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)

     File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py", line 188, in render_to_string
       return t.render(context_instance)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 123, in render
       return self._render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 117, in _render
       return self.nodelist.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 744, in render
       bits.append(self.render_node(node, context))

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 757, in render_node
       return node.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py", line 127, in render
       return compiled_parent._render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 117, in _render
       return self.nodelist.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 744, in render
       bits.append(self.render_node(node, context))

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 757, in render_node
       return node.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py", line 127, in render
       return compiled_parent._render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 117, in _render
       return self.nodelist.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 744, in render
       bits.append(self.render_node(node, context))

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 757, in render_node
       return node.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py", line 64, in render
       result = block.nodelist.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 744, in render
       bits.append(self.render_node(node, context))

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 757, in render_node
       return node.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py", line 64, in render
       result = block.nodelist.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 744, in render
       bits.append(self.render_node(node, context))

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 757, in render_node
       return node.render(context)

     File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py", line 227, in render
       nodelist.append(node.render(context))

     File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 885, in render
       return func(*func_args)

     File "/var/www/rizzyhome.com/www/django/rizzyhome/products/templatetags/yair.py", line 108, in thumbnail
       import Image, ImageOps

     File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 45, in <module>
       __import__("FixTk")

     File "/usr/lib/python2.7/lib-tk/FixTk.py", line 15, in <module>
       import ctypes

     File "/usr/lib/python2.7/ctypes/__init__.py", line 549, in <module>
       CFUNCTYPE(c_int)(lambda: None)

    MemoryError

编辑:添加代码
import os, errno

from django import template
from django.conf import settings

register = template.Library()

def _mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc: # Python >2.5
        if exc.errno == errno.EEXIST:
            pass
        else: raise

@register.simple_tag
def thumbnail(image_url, width, height, THIS_ROOT=settings.MEDIA_ROOT, THIS_URL=settings.MEDIA_URL, img_w=None, img_h=None, method="crop"):
    """
    Given the url to an image, resizes the image using the given width and 
    height on the first time it is requested, and returns the url to the new 
    resized image. If width or height are zero then the original ratio is 
    maintained.
    """

    if not img_w:
        img_w = width

    if not img_h:
        img_w = height

    image_url = unicode(image_url)

    # determine new paths
    resized_image_reduced = os.path.join('_resized_', image_url.replace(THIS_ROOT, ''))

    file_name, file_ext = os.path.basename(resized_image_reduced).split(os.extsep)
    resized_image_absolute_path = os.path.join(
        THIS_ROOT,
        os.path.dirname(resized_image_reduced),
        u'%s__%05d-%05d_%s%s%s' % (file_name, width, height, method, os.extsep, file_ext)
    )
    resized_image_relative_url = os.path.join(
        THIS_URL,
        os.path.dirname(resized_image_reduced),
        u'%s__%05d-%05d_%s%s%s' % (file_name, width, height, method, os.extsep, file_ext)
    )

    # make sure target directory exists
    _mkdir_p(os.path.realpath(os.path.dirname(resized_image_absolute_path)))

    # abort if thumbnail exists, original image doesn't exist, invalid width or 
    # height are given, or PIL not installed, or thumbnail is newer than source image
    if os.path.exists(resized_image_absolute_path):
        if os.path.exists(image_url):
            if os.path.getmtime(resized_image_absolute_path) > os.path.getmtime(image_url):
                return resized_image_relative_url
        else:
            return resized_image_relative_url
    if not image_url:
        return ""

    try:
        width = int(width)
        height = int(height)
    except ValueError:
        return resized_image_relative_url

    if not os.path.exists(image_url) or (width == 0 and height == 0):
        return image_url

    try:
        from PIL import Image, ImageOps
    except ImportError:
        return resized_image_relative_url

    # open image, determine ratio if required and resize/crop/save
    image = Image.open(image_url)
    if width == 0:
        width = image.size[0] * height / image.size[1]
    elif height == 0:
        height = image.size[1] * width / image.size[0]
    if image.mode not in ("L", "RGB"):
        image = image.convert("RGB")

    try:
        if method == 'scale':

            image.thumbnail((width, height), Image.ANTIALIAS)


            new_w, new_h = image.size

            x1 = (img_w-new_w) /2
            y1 = (img_h-new_h)

            new_image = Image.new(image.mode, (img_w, img_h), (255,255,255))
            new_image.paste(image, (x1,y1))

            new_image.save(
                resized_image_absolute_path,
                "JPEG",
                quality=100
            )

        elif method == 'crop':
            image = ImageOps.fit(image, (width, height), Image.ANTIALIAS)
            image.save(
                resized_image_absolute_path,
                "JPEG",
                quality=100
            )

    except Exception, e:
        raise
        return resized_image_relative_url

    return resized_image_relative_url

我将(修改后的)脚本附加到了我的原始帖子中,谢谢! - sframe
你们在生产环境中运行SELinux吗?对于一些启用了selinux的平台,ctypes存在一些已知问题:http://stackoverflow.com/questions/3762566/occasional-ctypes-error-importing-numpy-from-mod-wsgi-django-app - GDorn
您是否有可能在生产环境中已经用尽了可用的RAM和交换空间?也许是因为最初启动了太多的Apache进程? - Frank Wiles
@GDom:我不认为我启用了SElinux。怎么才能知道呢? - sframe
@Frank Wiles:我最初也是这样想的,但这是全新安装调整一个图像大小。非常令人沮丧。 - sframe
1个回答

5

非常感谢您的评论和提供的帮助。

显然,在 CTYPE 模块的 __init__.py 中存在一个奇怪的错误。-或者其他什么,我只是读到了 :)

对我来说,修复方法是注释掉 __init__.py 文件中的最后一行。似乎最后一行是专门为 Windows 64 位设计的,而这正是导致我的 Ubuntu 出问题的原因。

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=598727#38


刚在Python 2.7.3中遇到了这个问题,当尝试在bluehost上部署Mezzanine网站时。这真是一个巨大的惊喜,因为问题不在使用的代码中,而是在自己的代码中出现了错误。感谢您发布这个问题。 - Feanor
现在是2021年,我不得不使用这个丑陋的解决方法... 我正在使用Centos 7 + Apache + Django 3.2 + 手动安装的Python 3.7 + 手动安装的mod_wsgi。我想知道我做错了什么导致出现这个老错误。我感到非常沮丧。感谢@sframe的回答。 - José

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接