Category Archives: Python

Fixing OSError: cannot write mode RGBA as JPEG in Python

I have an application that was originally written in Python 2.7 and used the Python Image Libary (PIL). Now it uses Python 3.x and Pillow (the PIL replacement). One of the things it does is automatically generate .jpg file thumbnails of uploaded files.

It does this by resizing the uploaded image, and then saving it with the filename extension changed.

I started getting an error when uploading a .png file:

OSError: cannot write mode RGBA as JPEG

A bit of research told me that the behavior has changed. Now you need to discard the alpha (transparency) channel of an image before you’re allowed to save it as an image type that doesn’t have an alpha channel. Since PNG files normally have a transparency layer, it makes sense why I would hit that error. It’s trying to protect me from losing data I might potentially want to keep. However, I don’t want or need alpha channel data for my thumbnails.

The solution is just to convert the image before saving.

thumbnail = im.convert('RGB')
thumbnail.save("my_image_filename.jpg", 'JPEG', quality=92)

It’s a simple fix, but slightly annoying that the behavior has changed over the years.

Updating Django 1.8 on Python 2.7 to Django 1.11 on Python 3.6

I recently updated a few Django apps from Python 2.7 to Python 3.6 and while going from Django 1.8 to Django 1.11. This is mainly for my own reference, but others may find it useful.

Move the existing virtualenv (this will break the app):

mv ~/.virtualenvs/wbstats ~/.virtualenvs/wbstats2

Create a new virtualenv:

mkvirtualenv -p /usr/bin/python3 wbstats

At this point it might be a good idea to update the version of Django in requirements.txt. For WbStats it moved from 1.8 to 1.11.

Pip install the requirements.txt:

pip install -f requirements.txt

Edit settings.py and make sure there is a TEMPLATES section, which replaces TEMPLATE_DIRS. In addition, TEMPLATE_CONTEXT_PROCESSORS no longer exists. Basically anything with TEMPLATE_ has been rolled into the TEMPLATES section.

You may need to change some imports, i.e.

from models import *

may become:

from stats.models import *

The URLs will probably choke because strings are no longer allowed. Do not import “patterns”. Urlpatterns now is an array: urlpatterns = [url(…), url(…)]

'stats.views.index'

may need to be changed to:

from stats import views
views.index

After imports are fixed, the next thing will probably be fixing print statements.

Urlparse has been moved.

import urlparse

becomes:

import urllib.parse as urlparse

If you updated Django you’ll probably need to run migrations.

python manage.py migrate

Admin commands will need to be ported:

     option_list = BaseCommand.option_list + (make_option('-d', '--domain', default=None, action='store', type='string', dest='domain', help='The name of a domain to create or update.'),)

Becomes:

     def add_arguments(self, parser):
          parser.add_argument('-d', '--domain', default=None, action='store', dest='domain', help='The name of a domain to create or update.')

The parser arguments are mostly the same, but  references to “type=’int'” should be changed “type=int” without quotes, otherwise you’ll get ValueError: ‘int’ is not callable.

There’s some code in some of the admin commands I’ve written that changes the codec for stdout:

UTF8Writer = codecs.getwriter(‘utf8’)
sys.stdout = UTF8Writer(sys.stdout)

This will NEED to be removed because it causes cryptic TypeError problems saying things must be str and not bytes.

render_to_response needs to change to render because context_instance doesn’t exist.

MusicSrch Reboot

Early in 2016 I bought the source code for a music search site from a fella in Slovenia and put it under the umbrella of the WbSrch search engine.

When WbSrch shut down later in 2016, it was left in limbo. It was still running through 2017, but ignored. And sometimes the service crashed and wouldn’t be started back up for a while. Like, sometimes even months.

When I started curating for RCRDList, it became something that I wanted to use again. But it was pretty broken, and I never really got around to learning Ruby. So I spent a long weekend and a few evenings rewriting it in Python and JavaScript.

It doesn’t search all of the same services that it used to, but it searches more of them now, especially more of the mainstream services. There are a few more things I’d like to add, but it already does more than the original version did. I also don’t have to worry about the service crashing because it’s a Python app, and I know how to keep those running consistently.

Try it out at:

https://musicsrch.com

 

New Game: Dragon Wilds

http://dragonwilds.com

I built this oldschool over-the-2400-baud-modem game in my spare time over the past week using Python and Django (it’s about 500 lines of source code, 500 lines of HTML templates). I don’t know whether I’m going to spend more time on it, but it was fun to build and a nice break from the to-complex-to-work-on-with-the-brainpower-I-have-left-after-work state Basternae 3 is in. If people like it I’ll probably make more of them or improve the existing game. First time I’ve done a web-only game.

Let me know if you can break it. As can be expected, there’s really not that much depth to it and you may well get tired of it quickly.

A Better To-Do List: Got-It-Done.com

If you’ve explored this blog much in the past you would have noticed that I had a “to do list” published.  It wasn’t well-sorted, and not all that easy to edit.

Since much of what I do in life is todo-list-driven, I’ve always tended to fill post-its and notebook pages with lists of things I need to get done, lists of ideas, tasks, etc.  While I’m at work, I’ll think of things I need to do and jot them down on whatever scrap of paper is handy.  It helps me stay focused, but I tend to have quite a clutter of papers on my desk.

The perfect solution for me to get rid of some of the clutter and make these lists available to me in more places than just my desk is an online solution.  There are already a solid handful of sites you can use to do that, but I’m far too hardcore for my own good.

Instead, since I wanted to get more familiar with the Django web framework and the jQuery JavaScript library, I built my own online task management application.  It was fun, challenging, and immediately useful.  I’ve moved the Basternae to-do-list to it and make use of it for everyday organization.

It’s free to create an account, so feel free to try it if it’s something you might find useful.  Here’s a screenshot of it in action:

Got-It-Done Task List Screenshot

Check it out at http://got-it-done.com.  It’s pretty beta, so feel free to offer suggestions and/or let me know if you have any errors.

Integrating Python?

One of the things I’ve been worrying over is how to write a new scripting and artificial intelligence engine that integrates all the buttery goodness and capabilities of MobProgs and the homebrew probability-based AI system I wrote for Basternae II along with the only-used-once movement scripts I put together. They were all pretty powerful, but the bad things are/were:

1. Too many pieces of code to maintain.
2. Required a programmer’s full attention — far too complex for a zone writer or newbie-level web scripter to use.
3. Always required a recompile if changes were made.
4. Always required a reboot to load new changes. This made it un-tweakable. Want a mob to cast fireball half as often? Change it and reboot the MUD.
5. Extremely zone-dependent. If we unload the plane of fire, we still have all of the plane of fire scripts active, including hard-coded mob names and numbers.

It definitely shouldn’t require a restart of the game just to make a troll kick someone in the head more often. This naturally leads me to Python and/or IronPython, since it’s my current obsession. I have some reading to do, but don’t be surprised if I come up with a scripting engine of pure awesomeness.