Python SVG writer

I've written dozens of different Python programs that write SVGs of various types, so I thought it was about time I wrote a single generic module to make writing SVGs easy. Unsurprisingly, I'm not the only person to have had this idea, but rather than try to learn how to use someone else's module, I decided to write my one. It's more fun anyway. If anyone else wants to use the module it's available to download (and edit) on Github:

https://github.com/petercollingridge/DrawSVG

There's also a wiki that explains how to use the module:

DrawSVG wiki

I expect to keep adding to the program and creating helper modules (such as one for drawing graphs), which is why it's on Github. The basics are already in place, and I think it''s pretty straightforward to use. You do need to know how SVG works - I have a tutorial if you don't. Below is a quick guide on how to use my SVG-writer.

Basics

To create an SVG:

from DrawSVG import SVG

mySVG = SVG()

To write the SVG to file:

mySVG.write('test.svg')

Creating elements

Elements are created, with the element type as the first argument, a dictionary of attributes as an optional second element, and a child as an optional third element:

mySVG.addChildElement('rect',
                     {'x':20,
                      'y':40,
                      'width':80,
                      'height':50,
                      'fill': 'blue'})
mySVG.addChildElement('text',
                     {'x':22, 'y':12,},
                      "Test text")

Which creates an SVG like this:

<svg version="1.1"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 xmlns="http://www.w3.org/2000/svg">
  <rect y="20" x="20" height="20" fill="blue" width="60"/>
  <text y="12" x="22">Test text</text>
</svg>

Note that there is nothing (yet) in the code to check that elements are valid or have the required attributes. Also, attributes appear in a random order because they're kept in a dictionary. The reason I pass a dictionary rather than generate one with **kwargs is that often the attribute names will be hyphenated (e.g. 'stroke-width'), which Python doesn't like outside of a string.

Editing elements

This is one area I want to improve in future. For now, when you create an element, it is returned, which allows you to bind it to a variable (which could be put in a dictionary of elements if you want to refer to them later. For example, you could replace the code that creates a text element with this:

text_element = mySVG.addChildElement('text')
text_element.attributes['x'] = 22
text_element.attributes['y'] = 12
text_element.addChildElement('Test text')

This is useful for creating nested groups:

g = mySVG.addChildElement('g', {'fill':'blue'})
g.addChildElement('rect',
                 {'x':20,
                  'y':20,
                  'width':60,
                  'height':20})
g.addChildElement('text',
                 {'x':22, 'y':12,},
                  "Test text")

Another point to note (one I'm pretty pleased with): SVG inherits from the SVG_Element class so can be treated in the same way. For example, you can define the attributes of the SVG when it's created:

mySVG = SVG({'width':200, 'height':100})

Or later:

mySVG.attributes['viewBox'] = '0 0 100 100'

CSS

One difference between the SVG and other SVG elements is that it can be contain a style element that creates CSS. When adding a style, the first argument is the CSS selector and the following is a dictionary of attribute: value. For example:

mySVG.addStyle('rect', {'fill': 'blue'})
mySVG.addStyle('.my-text',
              {'font-size': 12,
               'font-family': 'Arial,sans-serif'})

This will create a style element like this:

<style> 
  .my-text{
    font-size:	 12;
    font-family: Arial,sans-serif;
  }
  rect{
    fill: blue;
  }
</style> 

There are still a few issues to sort out, and many ways to improve it, but even as it stands, I find it quite useful.

Comments

Thanks, Peter, for much informations about SVG which are not, in my opinion, well covered over Internet or not well explained as you did.

I didn't mean get involved with Python, but after this I wish to find time for that too.

All the best!

Thanks Alex, I'm glad you found my website useful. I've actually been meaning to write a full SVG tutorial for a while now, but haven't had the time. Maybe soon. I would definitely recommend getting involved with Python if you can.

Just browsing on the subject of SVG rotating objects and found your site and hence this.  I'm the author of playSVG https://github.com/cosmo-guffa/play-svg which serves a similar purpose.  However, it contains more abstractions for geometric objects, OO path representation, and the building of SVG elements.  One advantage of your code is the inclusion of CSS styles, great idea !  I'm considering implementing this in my work so thanks for the inspiration.  I would love to have someone knowledgeable like you take a look at my code and give feedback, but if you're not into reading others code, I can understand.   Thanks for sharing :)

Post new comment

The content of this field is kept private and will not be shown publicly.