vroomfondel
vroomfondel

Reputation: 3106

Python print length OR getting the size of several variables at once

In Python, if I print different data types separated by commas, they will all act according to their __str__ (or possibly __repr__) methods, and print out a nice pretty string for me.

I have a bunch of variables like data1, data2... below, and I would love to get their total approximate size. I know that:

I'd like to avoid dealing with different data types individually. Is there any way to leverage a function like print to get the total length of data? I find it quite unlikely that something like this is not already built into Python.

>>> obj.data1 = [1, 2, 3, 4, 5]
>>> obj.data2 = {'a': 1, 'b':2, 'c':3}
>>> obj.data3 = u'have you seen my crossbow?'
>>> obj.data4 = 'trapped on the surface of a sphere'
>>> obj.data5 = 42
>>> obj.data6 = <fake a.b instance at 0x88888>
>>> print obj.data1, obj.data2, obj.data3, obj.data4, obj.data5, obj.data6
[1, 2, 3, 4, 5] {'a': 1, 'c': 3, 'b': 2} have you seen my crossbow? trapped on the surface of a sphere 42 meh

I'm looking for something like:

printlen(obj.data1, obj.data2, obj.data3, obj.data4, obj.data5, obj.data6)
109

I know most of you could write something like this, but I'm mostly asking if Python has any built-in way to do it. A great solution would show me a way to return the string that print prints in Python 2.7. (Something like print_r in PHP, which I otherwise feel is wholly inferior to Python.) I'm planning on doing this programmatically with many objects that have pre-filled variables, so no writing to a temporary file or anything like that.

Thanks!

As a side-note, this question arose from a need to calculate the approximate total size of the variables in a class that is being constructed from unknown data. If you have a way to get the total size of the non-callable items in the class (honestly, the total size would work too), that solution would be even better. I didn't make that my main question because it looks to me like Python doesn't support such a thing. If it does, hooray!

Upvotes: 0

Views: 1458

Answers (5)

Terrel Shumway
Terrel Shumway

Reputation: 756

"A great solution would show me a way to return the string that print prints in Python 2.7."

This is roughly what print prints (possibly extra spaces, missing final newline):

  def print_r(*args):
      return " ".join((str(arg) for arg in args))

If you run in to lots of objects that aren't str-able use safer_str instead:

  def safer_str(obj):
      return str(obj) if hasattr(obj,"__str__") else repr(obj)

Upvotes: 1

If you have an object structure and you want to know how much does it require to store it, you could also pickle/cpickle the object and use that number as a measure, and to also to store the data into database.

Upvotes: 0

ikkuh
ikkuh

Reputation: 4603

This should now do it correctly:

def printlen(*args):
    return sum(map(len, map(str, args)))

For objects which do not support the str(obj) function. You could replace the str with a self made function or lambda:

def printlen(*args):
    return sum(map(len, map(lambda x: str(x) if hasattr(x, '__str__') else '', args)))

Upvotes: 1

Pouya
Pouya

Reputation: 159

If you want the length you can use this:

printlen = lambda *x: print(sum(len(str(i)) for i in x))

usage:

printlen(obj1, obj2, ..)

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121584

First of all, sys.getsizeof() is not the method to use to determine printed size. A python object memory footprint is a poor indicator for the number of characters required to represent a python object as a string.

You are looking for len() instead. Use a simple generator expression plus sum() to get a total:

def printlen(*args):
    if not args:
        return 0
    return sum(len(str(arg)) for arg in args) + len(args) - 1

The comma between expressions tells print to print a space, so the total length print will write to stdout is the sum length of all string representations, plus the whitespace between the elements.

I am assuming you do not want to include the newline print writes as well.

Demo:

>>> printlen(data1, data2, data3, data4, data5, data6)
136

Upvotes: 1

Related Questions