Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
MaberMK
Feb 1, 2008

BFFs

Sailor_Spoon posted:

Breaking a string inside parentheses is preferred. Like so:

code:
In [1]: assert False, ('hey '
   ...:                'whats up?')
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)

/Users/user/<ipython console> in <module>()

AssertionError: hey whats up?
I think backslashes for line continuation are really ugly, and if you're not cool enough to have an editor that highlights trailing whitespace, they're another way to introduce some hard to spot errors.

I'm not sure where you got the "string inside parentheses" thing is preferred, considering PEP8 says nothing about a preferred way to split strings. Moreover, I don't think using a line span is ugly at all; PEP8 even has an example using them to split conditional statements across lines. There's nothing wrong with using a line span.

Adbot
ADBOT LOVES YOU

good jovi
Dec 11, 2000

'm pro-dickgirl, and I VOTE!

MaberMK posted:

I'm not sure where you got the "string inside parentheses" thing is preferred, considering PEP8 says nothing about a preferred way to split strings. Moreover, I don't think using a line span is ugly at all; PEP8 even has an example using them to split conditional statements across lines. There's nothing wrong with using a line span.

from PEP8:

quote:

The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces. If necessary, you can add an extra pair of parentheses around an expression, but sometimes using a backslash looks better. Make sure to indent the continued line appropriately. The preferred place to break around a binary operator is *after* the operator, not before it.

Yes, that is not specifically addressing strings, but those are still on lines, aren't they? I do tend to use backslashes in long boolean expressions, but never feel good about it.

Spime Wrangler
Feb 23, 2003

Because we can.

Ahernia posted:

I'm trying to use Tkinter's Canvas to produce a vector map of Great Britain :britain: that you can pan around in, and zoom into.


The canvas.scale method is this (for x and y but shown only for x):

code:
x = ((x - a) * b) + a
Where 'a' is the x coordinate the zoom function was performed at, so you scale away from that point, and 'b' is the scaling factor. What would be the equivalent functions that update the value of 'a' and 'b', such that I can transform an old coordinate to a new coordinate?

I don't even know what mathematics this involves, or the name of it, so even that would be helpful. I posted this question in here in the hopes that maybe somebody has had to do the same thing, as it seems to be a byproduct of the tkinter canvas not having a viewport.

What you're looking for is the Affine Transformation. It doesn't really use much more math than you're already doing, but the wiki description is pretty mathspeak-heavy.

Think of it like, whenever you pan or zoom the map you find two points in the X-direction and two points in the Y-direction on both the map coordinates and the view coordinates, and fit a line (ala y = m*x+b) to each.
Like:
code:
   *
   |
*--|--*
   |
   *
but you can also use the corners of the view or pretty much any 4 unique points whose location you know both in map-space and view-space.

So you get one equation y_view = m1*x_map + b1 and one equation x_view = m2*y_map + b2.

Then to transform a point [x_map, y_map] from map coordinates to the view coordinates you just plug in your map coords and out pop the view coords. This will scale, translate, and skew a set of coordinates.

Then every time you change the location of the view, redo that operation to get a new set of m's and b's.

I hope that helps, and that my math is correct. (I'm on no sleep and in a bit of a hurry so I didn't check anything)

You might also look into the Basemap toolkit for matplotlib i mentioned on the last page. Not sure if it'll fit your needs, but it's a readymade mapping system.

MaberMK
Feb 1, 2008

BFFs

Sailor_Spoon posted:

from PEP8:


Yes, that is not specifically addressing strings, but those are still on lines, aren't they? I do tend to use backslashes in long boolean expressions, but never feel good about it.

I stand corrected. I searched the document for 'string' and variations thereof but came up with nothing. I'll remember that one.

Ahernia
Feb 9, 2005

Spime Wrangler posted:


So you get one equation y_view = m1*x_map + b1 and one equation x_view = m2*y_map + b2.

Then to transform a point [x_map, y_map] from map coordinates to the view coordinates you just plug in your map coords and out pop the view coords. This will scale, translate, and skew a set of coordinates.

Then every time you change the location of the view, redo that operation to get a new set of m's and b's.


So you initially store an (x,y) value from the unmoved coordinate space, then every time the canvas got moved/scaled, find an affine transformation between the initial (x,y) and the newest (x,y). And that would be valid for all 'old' (x,y) values in the coordinate space?

Spime Wrangler
Feb 23, 2003

Because we can.

Well, the way I'd do it would be to have a map coordinate space that corresponds to real world locations and, unless it became a big performance hit, reproject the map data each time the view moved. For just translations I bet you're just fine with a relative method, but for stuff like scaling your probably going to have an easier time recalculating from the map coordinates.

But if some one has a better idea please say so cus my experience is mostly limited to gis and static displays.

However, I think you definitely want to keep a master set of data in the map coordinates, and work from there, especially if you ever want to interface with other datasets, map software, or export any data for other people to use.

Ahernia
Feb 9, 2005
That's probably what I will end up doing (just transforming everything that could be displayed), it just seemed like something I should be able to figure out. I'm probably naively assuming the maths isn't complex.

I guess it's solving a recursive function maybe? It's just so frustrating that movement is so easy to understand (just keep summing your offsets), and scaling is so hard.

echinopsis
Apr 13, 2004

by Fluffdaddy
This is regarding namespace. If I have a instance, say primaryclass, and it has a variable called self.var, and from within that instance I open another instance, say secondaryclass, when I'm in secondaryclass, how do I reference that self.var, do I have to pass it as a argument?

Haystack
Jan 23, 2005





echinopsis posted:

This is regarding namespace. If I have a instance, say primaryclass, and it has a variable called self.var, and from within that instance I open another instance, say secondaryclass, when I'm in secondaryclass, how do I reference that self.var, do I have to pass it as a argument?

Yup. That's often the main purpose of an __init__ method.

code:
class PrimaryClass(object):
    var = True
    
    def __init__(self):
        whatevs = SecondaryClass(self.var)
        
class SecondaryClass(object):
    def __init__(self, var):
        print var == True

if __name__ == "__main__":
    primary = PrimaryClass() #True

tef
May 30, 2004

-> some l-system crap ->

echinopsis posted:

This is regarding namespace. If I have a instance, say primaryclass, and it has a variable called self.var, and from within that instance I open another instance, say secondaryclass, when I'm in secondaryclass, how do I reference that self.var, do I have to pass it as a argument?


well, you can pass the parent object as an argument


class Foo(object):
def __init__(self,parent)


But really what are you trying to do exactly? break encapsulation

Scaevolus
Apr 16, 2007

Ahernia posted:

That's probably what I will end up doing (just transforming everything that could be displayed), it just seemed like something I should be able to figure out. I'm probably naively assuming the maths isn't complex.

I guess it's solving a recursive function maybe? It's just so frustrating that movement is so easy to understand (just keep summing your offsets), and scaling is so hard.

I feel your pain, having had to convert from a world space with +y being down and +z being left to screen space with +x being down and +y being right. (Minecraft :argh:)

Some tips:

Three floats can represent the state of your view.
center_x, center_y -- where the center of the map is, in world coordinates
zoom -- the scale level. Less is more zoomed out.


Then given canvas_width and canvas_height

You can calculate where the corners of the canvas are pointing at, in world coordinates:
map_topleft_x = center_x - width / (zoom * 2)
map_topleft_y = center_y - height / (zoom * 2)
map_bottomright_x = center_x + width / (zoom * 2)
map_bottomright_y = center_y + height / (zoom * 2)


Say the user drags the map right by 50px on the screen:
center_x -= 50. / zoom

Does that help at all?

Aafter
Apr 14, 2009

A is for After.
Alright, I wrote a program for Minecraft to measure how many blocks you will need for a project. Stacks as well. Its my first real program, so any criticism or tips would be awesome.

code:
measurement = raw_input('Which measurement? (area, perimeter, peel): ')

if measurement == 'area':

	length = input("How long? ")
	width = input("How wide? ")

	blocks = length*width
	stacks = blocks/64.0

	print str(blocks) + ' blocks'
	print str(stacks) + ' stacks'

elif measurement == 'perimeter':
	
	length = input("Length? ")
	width = input("Width? ")
	
	blocks = (length + width) * 2 - 4
	stacks = blocks/64.0

	print str(blocks) + ' blocks'
	print str(stacks) + ' stacks'

elif measurement == 'peel':

	length = input("Length? ")
	width = input("Width? ")
	height = input("Height? ")
	
	blocks = ((width + length) * 2 - 4) * height + (2 * (length * width)) - ((width + length) * 2 - 4)
	stacks = blocks/64.0

	print str(blocks) + ' blocks'
	print str(stacks) + ' stacks'


else:

	print "You're stupid. Try again."
EDIT: After reviewing it just now, I realized that I could put 'stacks' up top instead of typing it over and over.

Aafter fucked around with this message at 07:13 on Nov 12, 2010

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



Aafter posted:

EDIT: After reviewing it just now, I realized that I could put 'stacks' up top instead of typing it over and over.

You're asking for width/length in every case, which can be put before the measurement check. The stacks part needs to go after, as blocks has no value until after the measurement check.

code:
measurement = raw_input('Which measurement? (area, perimeter, peel): ')

length = input("Length? ")
width = input("Width? ")
blocks = None

if measurement == 'area':
	blocks = length*width
elif measurement == 'perimeter':
	blocks = (length + width) * 2 - 4
elif measurement == 'peel':
	height = input("Height? ")
	blocks = ((width + length) * 2 - 4) * height + (2 * (length * width)) - ((width + length) * 2 - 4)
else:
	print "You're stupid. Try again."

stacks = blocks/64.0

print str(blocks) + ' blocks'
print str(stacks) + ' stacks'
Edit: Unless you plan to use the stacks variable later, you could even not have it and just print str(blocks/64.0) + ' stacks'

Carthag Tuek fucked around with this message at 07:56 on Nov 12, 2010

DirtyDiaperMask
Aug 11, 2003

by Ozmaugh
Consider separating out the formulas used to calculate blocks needed. I a Pythonic way to do so would be to create a dictionary where the keys are strings representing valid answers to the "Which calculation do you want?" question and the values are the functions themselves. For example:
code:
funcs = {"volume":lambda l, w, h: l * w * h, "surface":lambda l, w, h: 2*w*l + 2*l+h + 2*w*h}
Lambdas used for brevity, but there's no reason you couldn't simply define full functions and store them in the dictionary. Then use something like this to run the correct function.

code:
measurement = raw_input('Which measurement? (area, perimeter, peel): ')

length = input("Length? ")
width = input("Width? ")
height = input("Height? ")

funcs[measurement](length, width, height)

The real advantage to this sort of approach is that it makes it easier to extend the program if you need to add more calculation. Say, one that gives the number of non-visible interior cubes(or whatever, I don't play Minecraft). You simply add a function for it to the dictionary, rather than having to add on another case to your lengthy if-elif chain.

Lurchington
Jan 2, 2003

Forums Dragoon

DirtyDiaperMask posted:

The real advantage to this sort of approach is that it makes it easier to extend the program if you need to add more calculation. Say, one that gives the number of non-visible interior cubes(or whatever, I don't play Minecraft). You simply add a function for it to the dictionary, rather than having to add on another case to your lengthy if-elif chain.

code:

import abc

class Calculation(object):
    """
    @ivar width: width of thing
    @type width: C{float}
    @ivar length: length of thing
    @type length: C{float}
    """
    __metaclass__ = abc.ABCMeta
    def __init__(self):
        self.length = int(input('Length? '))
        self.width = int(input('Widgth? '))

    @abc.abstractproperty
    def blocks(self):
        """
        the amount of blocks given the provided length and width
        """
    @property
    def stacks(self):
        return self.blocks / 64.0

    @property
    def results(self):
        return '{0}: blocks={1} stacks={2}>'.format(self.__class__.__name__,
                                                    self.blocks,
                                                    self.stacks)
class Area(Calculation):
    @property
    def blocks(self):
        return self.width * self.length

class Perimeter(Calculation):
    @property
    def blocks(self):
        return (self.width + self.length) * 2 - 4

class Peel(Calculation):
    def __init__(self):
        super(Peel, self).__init__()
        self.height = int(input('Height? '))
    @property
    def blocks(self):
        return (((self.width + self.length) * 2 - 4) * self.height + 
                     (2 * (self.length * self.width)) - 
                     ((self.width + self.length) * 2 - 4))

def CalculationFactory():
    """
    This is a docstring
    """
    calc_map = dict(area=Area, perimeter=Perimeter, peel=Peel)
    user_input = None
    while user_input not in calc_map:
        user_input = raw_input('Which measurement? (area, perimeter, peel): ').lower()

    return calc_map[user_input]()

if __name__ == '__main__':
    
    calc = CalculationFactory()
    
    print calc.results
come on guys, there's no reason to half-rear end this thing :haw:

...

I'm kidding, no need to use epydocs.

edit: made more pretentious

Lurchington fucked around with this message at 16:56 on Nov 12, 2010

wins32767
Mar 16, 2007

Oh java, how I've missed you.

Zombywuf
Mar 29, 2008

wins32767 posted:

Oh java, how I've missed you.

Now there's a horror.

Stabby McDamage
Dec 11, 2005

Doctor Rope

Lurchington posted:

code:
...amazing...
come on guys, there's no reason to half-rear end this thing :haw:

...

I'm kidding, no need to use epydocs.

edit: made more pretentious

I've recently discovered that you can generate new class definitions dynamically, just as you can with functions. So maybe we can cram that in there? Something like

code:
class CalculationClassFactory(object):
    def __init__(self,block_type):
        self.block_type = block_type
    
    def create_class_type(self,calculation_type):
        class R(AbstractCalculation): pass
        p = CalculationBlockMethodProvider(self.block_type, calculation_type)
        R.blocks = p.get_blocks_calculation_method()
        return R
            
ccfactory = CalculationClassFactory(input("block type? "))
calculator_class = ccfactory.create_class_type(input("calculation type? "))
calculator = calculator_class() # instantiate
# ... use calculator

RobotEmpire
Dec 8, 2007
Here is this dumb thing I made for my first web app. When I say dumb, I mean really dumb, so don't blame me for stealing the ten seconds of your life it took to use.

Written in Python (obv), utilizing Python Imaging Library and Flask. It's not perfect or perfectly secure but I'm pretty happy with it! There are a bunch of ideas I have for it that I will work on intermittently but I think it does about what I want it to do; I'm looking for my next project now.

edit: Here's the source.

code:
import Image, ImageDraw, ImageFont
import sys
import random
from flask import Flask, render_template, request
from os import remove
##from flaskext.wtf import Form, TextField, validators
from wtforms import Form, TextField, validators

app = Flask(__name__)

class ImageForm(Form):
    ragetext = TextField('Enter Rage Text:', [validators.Length(min=1, max=12)])

@app.route('/', methods=['POST', 'GET'])
def index():
    form = ImageForm(request.form)
    if request.method == 'GET':
        return render_template('index.html', form=form)
    else:
        the_image=createimage(form.ragetext.data)
        return render_template('ragetext.html', img=the_image)

def createimage(text):
    image = Image.open("static/rageface.jpg")
    draw = ImageDraw.Draw(image)
    if len(text) <= 7:
        fontsize = 72
    else:
        fontsize = 48
##    font = ImageFont.truetype("ARIALBD.ttf", fontsize, encoding="unic")
    font = ImageFont.truetype("static/OldSansBlack.ttf", fontsize, encoding="unic")
    draw.text((10, 10), text, font=font, fill="red")
    newname = 'images/%s.jpg' % random.randint(0,1000000000)
    image.save(newname)
    return newname

if __name__ == "__main__":
    app.run(host='0.0.0.0', port='8080')

RobotEmpire fucked around with this message at 16:54 on Nov 14, 2010

Sindai
Jan 24, 2007
i want to achieve immortality through not dying
I have an image recognition module that uses numpy and nupic that was created and left behind by an old employee that I need to get working. Unfortunately I know little to nothing about python and after a lot of screwing around with PYTHONPATH this is as far as I can get:

code:
Traceback (most recent call last):
  File "Recognizer.py", line 12, in <module>
    import numpy
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/__init__.py", line 130, in <module>
    import add_newdocs
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/add_newdocs.py", line 9, in <module>
    from lib import add_newdoc
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/lib/__init__.py", line 152, in <module>
    from type_check import *
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/lib/type_check.py", line 8, in <module>
    import numpy.core.numeric as _nx
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/core/__init__.py", line 5, in <module>
    import multiarray
ImportError: No module named multiarray
There is no "multiarray.py" anywhere on the system, though there is a "multiarray.so" at "/usr/local/lib/python2.6/dist-packages/numpy/core/multiarray.so". Is that what I need and if so how do I tell python it's there?

Sindai fucked around with this message at 01:27 on Nov 16, 2010

RobotEmpire
Dec 8, 2007
Try reinstalling numpy. sudo apt-get install python-numpy

(yes the multiarray.so is what numpy should be seeking (and finding) normally)

if you go into the python shell and type

> import numpy.core
> numpy.core.multiarray


What does it say?

RobotEmpire fucked around with this message at 05:09 on Nov 16, 2010

No Safe Word
Feb 26, 2005

Sindai posted:

I have an image recognition module that uses numpy and nupic that was created and left behind by an old employee that I need to get working. Unfortunately I know little to nothing about python and after a lot of screwing around with PYTHONPATH this is as far as I can get:

code:
Traceback (most recent call last):
  File "Recognizer.py", line 12, in <module>
    import numpy
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/__init__.py", line 130, in <module>
    import add_newdocs
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/add_newdocs.py", line 9, in <module>
    from lib import add_newdoc
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/lib/__init__.py", line 152, in <module>
    from type_check import *
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/lib/type_check.py", line 8, in <module>
    import numpy.core.numeric as _nx
  File "/home/CSMART/trunk/vision/src/recognition/nta/nupic-1.7.1-linux64/lib/python2.5
/site-packages/numpy/core/__init__.py", line 5, in <module>
    import multiarray
ImportError: No module named multiarray
There is no "multiarray.py" anywhere on the system, though there is a "multiarray.so" at "/usr/local/lib/python2.6/dist-packages/numpy/core/multiarray.so". Is that what I need and if so how do I tell python it's there?

It looks like you're using Python 2.5 with that script and the multiarray.py you have is for Python 2.6

echinopsis
Apr 13, 2004

by Fluffdaddy
Often when using a for loop to iterate through a list, I often want to use the iteration amount for something, so I end up changing something nice like
code:
for eachdick in bagofdicks:
   eachdick+="comes with two hairy balls"
but end up changing it to
code:
for i in range(len(bagofdicks)):
   bagofdicks[i]+="comes with two hairy balls"
Just so I can get i.. Is there a way to retreive the index of eachdick from bagofdicks? I presume I can index=bagofdicks.index(eachdick) but it doesn't seem like it's the most elegant approach and maybe something else exists?

Lonely Wolf
Jan 20, 2003

Will hawk false idols for heaps and heaps of dough.
use `enumerate`

echinopsis
Apr 13, 2004

by Fluffdaddy
Thanks!

RobotEmpire
Dec 8, 2007
I'm going to replace foo/bar/baz with eachdick/backofdicks/"comes with two hairy balls" from here forward.

ErIog
Jul 11, 2001

:nsacloud:
I have a question that's bugging the poo poo out of me.

I'm writing a script to lightly mess with XML data that's the output of a horrible program that I have no way of controlling. I'm using ElementTree because it's the only XML library that doesn't make me want to tear my eyes out. I'm loving it except for the part where the output isn't being accepted back into the horrible program I mentioned before.

The way this horrible program handles XML is really dumb, but I can't change it. Its tags are case sensitive, it doesn't support the empty closing tag(<tag />) format that ElementTree spits out. So I read the documentation a little bit, and I switch the method to spitting out html. ElementTree in this instance does something equally stupid in this mode. It gives me my verbose empty tags, but it makes every drat closing tag lowercase so that the opening tags no longer match the closing tags.

quote:

<PrintCopies>1</printcopies>

Why the gently caress would it do this? Why does it care about the case of my tags? If it does care, then why does it only care about my closing tags?

I dug through the ElementTree source code a little bit, and I found the line I need to change. Is there an elegant way I can override a single function of a module or do I just need to bite the bullet, fork ElementTree into my project directory, patch it, and go on living my life?

ErIog fucked around with this message at 17:43 on Nov 17, 2010

Jonnty
Aug 2, 2007

The enemy has become a flaming star!

ErIog posted:

I have a question that's either going to make me sound really smart or really dumb.

I'm writing a script to lightly mess with XML data that's the output of a horrible program that I have no way of controlling. I'm using ElementTree because it's the only XML library that doesn't make me want to tear my eyes out. I'm loving it except for the part where the output isn't being accepted back into the horrible program I mentioned before.

The way this horrible program handles XML is really dumb, but I can't change it. Its tags are case sensitive, it doesn't support the empty closing tag(<tag />) format that ElementTree spits out. So I read the documentation a little bit, and I switch the method to spitting out html. ElementTree in this instance does something equally stupid in this mode. It gives me my verbose empty tags, but it makes every drat closing tag lowercase so that the opening tags no longer match the closing tags.


Why the gently caress would it do this? Why does it care about the case of my tags? If it does care, then why does it only care about my closing tags?

I dug through the ElementTree source code a little bit, and I found the line I need to change. Is there an elegant way I can override a single function of a module or do I just need to bite the bullet, fork ElementTree into my project directory, patch it, and go on living my life?

The best option is to submit the patch to the project and hope it gets included/they tell you how to manually disable it.

ErIog
Jul 11, 2001

:nsacloud:

Jonnty posted:

The best option is to submit the patch to the project and hope it gets included/they tell you how to manually disable it.

I should have been more specific in my post. Is there an elegant way around this that doesn't require me forking my own version of ElementTree so that I can get my script to work today? If there isn't then that's fine, it won't take me too long. I just want to make sure there's not something simple I'm missing about how Python works that would allow me to override just this one function from a module.

edit:

Thankfully Python is properly OOP so I was able to monkey patch it a lot easier than I thought. I cut and pasted the _serialize_xml function into my script, renamed it to erlog_serialize_xml, and then did:

code:
ET._serialize_xml = erlog_serialize_xml
All it took was some slight editing of the function to fix the scope problems of doing that, but I was able to get exactly what I wanted without having to duplicate the entire module. I'm not sure which way of doing it is more ugly, but this way required less code.

ErIog fucked around with this message at 18:21 on Nov 17, 2010

Scaevolus
Apr 16, 2007

The real answer is that you want to be using lxml.

Lurchington
Jan 2, 2003

Forums Dragoon

Scaevolus posted:

The real answer is that you want to be using lxml.

I just wish it was simple to get the latest stuff on windows. Oh well.

echinopsis
Apr 13, 2004

by Fluffdaddy
I've got a bunch of functions I'm gonna stick in a module to clean up my code, but one of the functions relies on a value I define at the start of the "real" piece of code, but it complains it's not global. I don't want to resign myself to putting the define in the module but I can't think of an alternative..

Yakattak
Dec 17, 2009

I am Grumpypuss
>:3

Can anyone show a simple example of simplejson? I can't seem to wrap my head around it. All I want to do is take a str object that contains some JSON, and parse it :saddowns:

For instance:
code:
        data = simplejson.dumps('{"test":"string"}')
        results = simplejson.load(data)
        print results['test']
I figured it would print "string" but instead it gives me this:

code:
AttributeError: 'unicode' object has no attribute 'read'
:psyduck:

devilmouse
Mar 26, 2004

It's just like real life.

Yakattak posted:

code:
        data = simplejson.dumps('{"test":"string"}')
        results = simplejson.load(data)
        print results['test']

You're using dumps() to dump to a string but then using load() which reads from a file-stream like object. Use loads() since it's a string and all should be well.

Lurchington
Jan 2, 2003

Forums Dragoon
also, remember that python has built in module support for json (using the json module in 2.6) with the same interface. On the other hand, cjson is faster but has a completely different interface. Yay.

Yakattak
Dec 17, 2009

I am Grumpypuss
>:3

Lurchington posted:

also, remember that python has built in module support for json (using the json module in 2.6) with the same interface. On the other hand, cjson is faster but has a completely different interface. Yay.

Yeah but I heard simplejson is the fastest, other than cjson.

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

Lurchington posted:

also, remember that python has built in module support for json (using the json module in 2.6) with the same interface. On the other hand, cjson is faster but has a completely different interface. Yay.
don't use cjson, or I'll loving cut you

Yakattak posted:

Yeah but I heard simplejson is the fastest, other than cjson.
simplejson is the standard library module; it was adopted into the stdlib in 2.6. it's a little slower than my own module, jsonlib, but honestly nobody cares that much about json performance and 99% of people are better off using simplejson/stdlib anyway.

cjson is terrible / buggy / worthless; do not use it because it will irreversibly mangle anything you put through it

just do this:

code:
try:
  import json
except ImportError:
  import simplejson as json

Lurchington
Jan 2, 2003

Forums Dragoon
I'm working on a web project that chews threw ~1MB of JSON a every few seconds, and someone decided that every speed gain for JSON was worth it; thus, cjson. However I guess I haven't noticed the mangling part of it.

If jsonlib is faster than stdlib, and uses the same interface, I'd be interested.

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

Lurchington posted:

I'm working on a web project that chews threw ~1MB of JSON a every few seconds, and someone decided that every speed gain for JSON was worth it; thus, cjson. However I guess I haven't noticed the mangling part of it.

If jsonlib is faster than stdlib, and uses the same interface, I'd be interested.
It uses basically the same interface; if you need to use fancy features, the parameter names/order might differ.

I recommend people use the stdlib instead, since it's better supported and is under active development, but feel free to at least try mine out. It's been a while since I benchmarked it, but IIRC the speed difference is only like 5% and depends heavily on what types of data you're parsing.

You might also be interested in py-yajl, which is a binding to the event-based YAJL library. It's comparable to simplejson/jsonlib in speed, and if you need to you can write your own custom extension module to call YAJL directly and go even faster.

You can't beat cjson for speed. But it also has so many bugs that IMO it's just not worth considering a "JSON library"; more like a "hosed-up pseudo-repr() lib"

Here's a short list of some of its bugs that I've found:

quote:

1. cjson.decode('1')

Returns 1, should raise an exception. Similar issues exist for other atomic values, such as cjson.decode('"a"') and cjson.decode('true').

2. cjson.encode(1)

Returns '1', should raise an exception. Similar issue to #1.

3. cjson.decode('["\\/"]')

Should return ['/'] or [u'/'], but returns ['\\/']. This causes value corruption when parsing JSON from correct implementations.

4. cjson.encode(['/'])

Returns '["/"]', should return '["\\/"]'. Similar to #3, but instead of corrupting strings, causes a security issue documented at <http://t3.dotgnu.info/blog/insecurity/quotes-dont-help.html>.

4. cjson.encode([u'\U0001d11e'])

Returns '["\\U0001d11e"]', should return '["\\ud834\\udd1e"]'. This prevents serialising any character from the astral plane.

Note that the result is invalid JSON, and any conforming parser will raise an exception when parsing it. cjson doesn't, because it's not.

5. cjson.decode('["\\ud834\\udd1e"]')

Returns [u'\ud834\udd1e'], should return [u'\U0001d11e']. This prevents parsing any character from the astral plane.

6. cjson.decode('[0.3]')

Returns [0.299999], should return [Decimal('0.3')]. This can cause silent corruption of data passed through cjson. I don't know if simplejson does this also -- jsonlib doesn't.

7. Several cases where invalid JSON is parsed into an arbitrary garbage value. All of these ought to raise an exception, but do not.

cjson.decode('["\\1"]')
cjson.decode('[+1]')
cjson.decode('[00]')
cjson.decode('[01]')
cjson.decode('[0.]')
cjson.decode('[\x0c]') <- stdlib json fails on this one also
cjson.decode('[1 2]')
cjson.decode('{"a": 1 "b": 2}')

Adbot
ADBOT LOVES YOU

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
Janin: what license are python libs typically released under? If GPL is ok, you could re-wrap the C from Perl's JSON::XS, which is fast and pretty thoroughly tested

  • Locked thread