Giter VIP home page Giter VIP logo

pout's Introduction

Pout

A collection of handy functions for printing out variables and debugging Python code.

print didn't give enough information while debugging, pprint wasn't much better. I was also getting sick of typing things like: print("var = ", var).

Pout tries to print out variables with their name, and for good measure, it also prints where the pout function was called so you can easily find it and delete it when you're done debugging.

I use pout extensively in basically every python project I work on.

Methods

pout.v(arg1, [arg2, ...]) -- easy way to print variables

example

foo = 1
pout.v(foo)

bar = [1, 2, [3, 4], 5]
pout.v(bar)

should print something like:

foo = 1
(/file.py:line)

bar (4) =
[
        0: 1,
        1: 2,
        2:
                [
                        0: 3,
                        1: 4
                ],
        3: 5
]
(/file.py:line)

You can send as many variables as you want into the call

# pass in as many variables as you want
pout.v(foo, bar, che)

# a multi-line call is also fine
pout.v(
    foo,
    bar
)

pout.h() -- easy way to print "here" in the code

example

pout.h(1)
# do something else
pout.h(2)

# do even more of something else
pout.h()

Should print something like:

here 1 (/file.py:line)

here 2 (/file.py:line)

here N (/file.py:N)

pout.t() -- print a backtrace

Prints a nicely formatted backtrace, by default this should compact system python calls (eg, anything in dist-packages) which makes the backtrace easier for me to follow.

example:

pout.t()

should print something like:

15 - C:\Python27\lib\runpy.py:162
14 - C:\Python27\lib\runpy.py:72
13 - C:\Python27\lib\unittest\__main__.py:12
12 - C:\Python27\lib\unittest\main.py:95
11 - C:\Python27\lib\unittest\main.py:229
10 - C:\Python27\lib\unittest\runner.py:151
09 - C:\Python27\lib\unittest\suite.py:65
08 - C:\Python27\lib\unittest\suite.py:103
07 - C:\Python27\lib\unittest\suite.py:65
06 - C:\Python27\lib\unittest\suite.py:103
05 - C:\Python27\lib\unittest\suite.py:65
04 - C:\Python27\lib\unittest\suite.py:103
03 - C:\Python27\lib\unittest\case.py:376
02 - C:\Python27\lib\unittest\case.py:318
01 - C:\Projects\Pout\_pout\src\test_pout.py:50

        pout.t()

pout.p([title]) -- quick and dirty profiling

example

p("starting profile")
time.sleep(1)
p() # stop the "starting profile" session


# you can go N levels deep
p("one")
p("two")
time.sleep(0.5)
p() # stop profiling of "two"
time.sleep(0.5)
p() # stop profiling of "one"


# you can also use with
with p("benchmarking"):
    time.sleep(0.5)

should print something like:

starting profile - 1008.2 ms
  start: 1368137723.7 (/file/path:n)
  stop: 1368137724.71(/file/path:n)


one > two - 509.2 ms
  start: 1368137722.69 (/file/path:n)
  stop: 1368137723.2(/file/path:n)


one - 1025.9 ms
  start: 1368137722.68 (/file/path:n)
  stop: 1368137723.7(/file/path:n)

pout.x(arg1, [arg2, ...]) -- like pout.v but then will run sys.exit(1)

This just prints out where it was called from, so you can remember where you exited the code while debugging

example:

pout.x()

will print something like this before exiting with an exit code of 1:

exit (/file/path:n)

pout.b([title[, rows[, sep]]]) -- prints lots of lines to break up output

This is is handy if you are printing lots of stuff in a loop and you want to break up the output into sections.

example:

pout.b()
pout.b('this is the title')
pout.b('this is the title 2', 5)
pout.b('this is the title 3', 3, '=')

Would result in output like:

********************************************************************************
(/file/path:n)


****************************** this is the title *******************************
(/file/path:n)


********************************************************************************
********************************************************************************
***************************** this is the title 2 ******************************
********************************************************************************
********************************************************************************
(/file/path:n)


================================================================================
============================= this is the title 3 ==============================
===============================================================================
(/file/path:n)

pout.c(str1, [str2, ...]) -- print info about each char in each str

Kind of like od -c on the command line.

example:

pout.c('this')

will print something like:

Total Characters: 4
t	't'	\u0074	LATIN SMALL LETTER T
h	'h'	\u0068	LATIN SMALL LETTER H
i	'i'	\u0069	LATIN SMALL LETTER I
s	's'	\u0073	LATIN SMALL LETTER S
(/file/path:n)

This could fail if Python isn't compiled with 4 byte unicode support, just something to be aware of, but chances are, if you don't have 4 byte unicode supported Python, you're not doing much with 4 byte unicode.

pout.s(arg1, [arg2, ...]) -- easy way to return pretty versions of variables

Just like pout.v() but will return the value as a string

pout.ss(arg1, [arg2, ...]) -- easy way to return pretty versions of variables without meta information

Just like pout.vv() but will return the value as a string

pout.l([logger_name, [logger_level]]) -- turn logging on just for this context

Turns logging on for the given level (defaults to logging.DEBUG) and prints the logs to stderr. Useful when you just want to check the logs of something without modifying your current logging configuration.

example:

with pout.l():
    logger.debug("This will print to the screen even if logging is off")
logger.debug("this will not print if logging is off")

with pout.l("name"):
    # if "name" logger is used it will print to stderr
# "name" logger goes back to previous configuration

pout.tofile([path])

Routes pout's output to a file (defaults to ./pout.txt)

example:

with pout.tofile():
	# everything in this with block will print to a file in current directory
	pout.b()
	s = "foo"
	pout.v(s)
	
pout.s() # this will print to stderr

Customizing Pout

object magic method

Any class object can define a __pout__ magic method, similar to Python's built in __str__ magic method that can return a customized string of the object if you want to. This method can return anything, it will be run through Pout's internal stringify methods to convert it to a string and print it out.

Console commands

pout json

running a command on the command line that outputs a whole a bunch of json? Pout can help:

$ some-command-that-outputs-json | pout json

pout char

Runs pout.c but on the output from a command line script:

$ echo "some string with chars to analyze" | pout char

Install

Use PIP

pip install pout

Generally, the pypi version and the github version shouldn't be that out of sync, but just in case, you can install from github also:

pip install -U "git+https://github.com/Jaymon/pout#egg=pout"

Make Pout easier to use

When debugging, it's really nice not having to put import pout at the top of every module you want to use it in, so there's a command for that, if you put:

import pout
pout.inject()

Somewhere near the top of your application startup script, then pout will be available in all your files whether you imported it or not, it will be just like str, object, or the rest of python's standard library.

If you don't even want to bother with doing that, then just run:

$ pout inject

from the command line and it will modify your python environment to make pout available as a builtin module, just like the python standard library. This is super handy for development virtual environments.

pout's People

Contributors

jaymon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pout's Issues

pout.v function output needs to be better

It prints things like:

f = template_name(self)

which is just awful, this needs to be made better, at least print that it's a function and stuff since I'm confused every single time I print out a function

When overriding a Pout method

If you create a child class and set it on pout:

class Child(pout.Pout):
    def v(self, *args, **kwargs):
        if some_custom_checking():
            # do some custom printing

        else:
            return super(Child, self).v(*args, **kwargs)

I think this will screw up all the stack trace checking in _get_arg_info().

descriptor error

class Desc(object):
    def __get__(self, instance, klass):
        pout.v("__get__", instance, klass)

class Example(object):
    @Desc
    def foo(): pass

e = Example()
e.foo() # this should raise an IndexError

stacktrace:

File "/usr/local/lib/python2.7/site-packages/pout.py", line 1573, in v
    return pout_class.create_instance().v(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 1515, in v
    args = [u"{}\n\n".format(self._str(v['name'], v['val'])) for v in call_info['args']]
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 775, in _str
    s = u"{} = {}".format(name, self._str_val(val))
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 957, in _str_val
    vt = self._get_type(v)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 1186, in _get_type
    return vt.typename
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 198, in typename
    elif self.is_callable():
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 272, in is_callable
    return isinstance(self.val, collections.Callable) or isinstance(self.val, classmethod)
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/abc.py", line 131, in __instancecheck__
    subclass = getattr(instance, '__class__', None)
  File "example.py", line 34, in __getattribute__
    pout.v(k)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 1573, in v
    return pout_class.create_instance().v(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 1514, in v
    call_info = self._get_arg_info(args)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 456, in _get_arg_info
    args.append({'name': arg_name, 'val': arg_vals[i]})
IndexError: tuple index out of range

pout.locals()

a locals printer, this will just print out all the local values in whatever context it was called, so if you did this:

def foo():
    foo = 1
    bar = 2
    pout.l()

foo()

It would print out foo and bar values.

create a command that will inject itself into the python environment

This is how my shell script is doing it:

  # create a usercustomize python file to customize the python installation
  cp /path/to/sitecustomiz.py "$env/environ.py"

  # we map our custom environ.py file to the sitecustomize so it gets run when
  # our virtualenv python gets run
  py_d=$(find "$env/lib" -type d -name "python*")
  $(pushd "$py_d"; ln -s ../../environ.py sitecustomize.py; popd)

It would be cool if I could just call pout.inject and pout would take care of adding itself to the sitecustomize.py file

import sys

is_py2 = sys.version_info[0] < 3
if is_py2:
    import __builtin__ as builtins
else:
    import builtins
try:
    import pout
    builtins.pout = pout
except ImportError:
    pass

pout.x should work just like pout.v but exit at the end

I thought I had done this but it seems not because I keep trying to use it this way:

pout.x(foo, bar)

and it doesn't do what I expect and I have to change to:

pout.v(foo, bar)
pout.x()

and I want the former to work because I'm sick of doing the latter and I don't think pout.x() supporting exit codes really matters, I've never actually used that functionality

pout.w()

Just like time.sleep() but will print out where it was called from

import time
time.sleep(5)

pout.v(5)

pout.v(sentinal not in val)

pout.v(sentinal not in val)

Results in:

sentinalnotinval = True

but it should be:

sentinal not in val = True

dictionary keys

this doesn't print the key as expected:

d = {
    b'foo': b'bar'
}

pout.v(d)

will result in:

d (1) =
{
	'foo': b'bar'
}

but 'foo' should be b'foo'

Pout hangs on nltk.Text instance

import nltk.corpus
from nltk.text import Text
moby = Text(nltk.corpus.gutenberg.words('melville-moby_dick.txt'))
pout.v(moby) # will just hang

A register object handler

When you have custom objects you can specify them here with a callback that will handle printing to a string. This would be handy for prom.Orm objects.

The main idea for this would be that it would be really convenient to treat certain objects differently than the generic print, and it would be cool to be able to define how to handle these. For example, with prom.Orm objects, I find myself a lot of times doing this:

out.v(foo.fields)

So that I don't have to do the .fields.

pdb

import pdb; pdb.set_trace()

would this be something I should add to pout?

multiline function call with a trailing comma

Notice the trailing comma after che:

pout.v(
    "foo",
    "bar",
    "che",
)

You remove that comma (ie, "che", becomes "che") then it works, but fails if the comma is there, I think this is a relatively easy fix, it's just I had never run into it before

filepath should be relative to os.getcwd()

so if cwd was /foo/bar and you printed out:

foo (1) =
{
    'foo': 1
}

(/foo/bar/che/bazfile.py:574)

It would be better displayed as:

foo (1) =
{
    'foo': 1
}

(che/bazfile.py:574)

but non relative paths should stay as full paths.

add pout hooks to print bytes as binary and hex

It would really be nice to have something

b = b"\x0a\x00\x0a\x00\x91\x00\x00"

pout.hex(b)

b = "0a 00 0a 00 91 00 00"

(file.py:NNN)

which could be achieved with something like:

" ".join("{:02x}".format(ord(c)) for c in b) # b is a string
" ".join("{:02x}".format(c) for c in b) # b is an int

I'd like something similar with binary

b = b'\x91'

pout.bin(b)

b = "10010001"

(file.py:NNN)

which could be achieved with something like:

"{:08b}".format(int(b.encode("hex"), 16))

Unicode issue in keys

d = {'\xef\xbb\xbffo_timestamp': ''}
pout.v(d)

will result in:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/pout/__init__.py", line 1806, in v
    return pout_class.create_instance().v(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/pout/__init__.py", line 1671, in v
    args = ["{}\n\n".format(self._str(v['name'], v['val'])) for v in call_info['args']]
  File "/usr/local/lib/python2.7/site-packages/pout/__init__.py", line 817, in _str
    s = "{} ({}) = {}".format(name, count, self._str_val(val, depth=0))
  File "/usr/local/lib/python2.7/site-packages/pout/__init__.py", line 876, in _str_val
    depth=depth,
  File "/usr/local/lib/python2.7/site-packages/pout/__init__.py", line 1243, in _str_iterator
    k = k if name_callback is None else name_callback(k)
  File "/usr/local/lib/python2.7/site-packages/pout/__init__.py", line 873, in <lambda>
    name_callback= lambda k: "'{}'".format(k),
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)

pout.o()

basically just a pout wrapper around print(), so it basically will print out the stuff like pout.v() but not have any of the other stuff like file and line number and stuff, this came about because there are many times I need to print a lot of stuff in like a loop and pout.o() just makes the output have too many newlines.

Bonus points if calling pout.o() will trigger a shutdown function that prints out where all the pout.o calls were located at the end of the run.

This call failed

pout.v(ret, default_val, getattr(self.module, k, None), self.fields.get(k, None))

Partial stack trace:

    pout.v(ret, default_val, getattr(self.module, k, None), self.fields.get(k, None))
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 1556, in v
    return pout_class.create_instance().v(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 1497, in v
    call_info = self._get_arg_info(args)
  File "/usr/local/lib/python2.7/site-packages/pout.py", line 447, in _get_arg_info
    args.append({'name': arg_name, 'val': arg_vals[i]})
IndexError: tuple index out of range

pout.logging() method

something like:

with pout.logging():
   # some code here that logging would now be one for

# logging would go back to what it was before outside with

The idea is you could selectively turn on logging for a block of code, testdata already has code that goes through and modifies all the loggers, so that could be a good place to start

unexpected class instance behavior

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        pout.v(self)

f = Foo()

will result in some variation of TypeError: issubclass() arg 1 must be a class

aggregate profiling info

it would be cool to be able to do something like this:

for i in range(really_big_number):
    with pout.a("running foo"):
        foo()
    with pout.a("running bar"):
        bar()

and have it print all the aggregate time spent in "running foo" and "running foo"

break _str_val() into multiple methods

so right now _str_val is just a giant if/elif/else, but I would like to change it so it gets the type and then basically takes that type and does:

t = self._get_type(val)
func = getattr(self, "_str_{}".format(t.lower()))
return func(val, depth, **kwargs)

so each of the ifs will be broken into their own method, I think this will help with maintenance.

Each of those methods should take a dict that maps the type to function that will create the string value from that type, so, for example, for module it would be by default:

{
    "MODULE": self._str_val
}

But you could pass in a dict that changes that mapping so you could short circuit the generation and basically say all modules should just render with repr on down the line, the reason for this is to allow properties to be printed on modules, right now I just print the name because pout.v(sys) will choke if it tries to print out the property values, I think there is circular recursion with sys.modules.

filter line or something

something like pout.v but you can pass in a string and only lines that match that string will actually be printed, so...

pout.fv("find this string", foo, bar)

will only print lines that match "find this string" in foo and bar.

pout.b(i)

let's say I'm doing something like:

for i in range(50):
    pout.b(i)

pout will interpret the i as how many rows I want instead of as the title, this should be pretty easy to correct, just have pout check if the passed in value is a variable (eg, i) instead of a number (eg, 5), if it is the former treat it as a title, if it is the latter, treat it as the row count, if you want to have the row count in a variable, this could maybe be made to work:

pout.b(rows=i)

pout.s

returns pout.v() but in string format, so it can be logged or printed out, so just like v() there would be s() and ss()

blank line 'indentation' varies using the pout methods

thanks for sharing, i like using pout. my suggestion is to minimize the amount of blank lines in the output, i.e.:

self = __main__.SerialComm instance
<	
	id: 18368192672040
	
	path: src/dienstbot/main.py
	
	Ancestry:
		asyncio.protocols.Protocol (/usr/local/lib/python3.6/asyncio/protocols.py)
		asyncio.protocols.BaseProtocol (/usr/local/lib/python3.6/asyncio/protocols.py)
		object
	
	__str__:
		<__main__.SerialComm object at 0x10b4ad997128>
	
	Class Properties:
	
	Instance Properties:
		transport = SerialTransport(<_UnixSelectorEventLoop running=True closed=False debug=False>, <__main__.SerialComm object at 0x10b4ad997128>, Serial<id=0x10b55ddda3c8, open=True>(port='/dev/ttyU0', baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=0, xonxoff=False, rtscts=False, dsrdtr=False))
		queue = <Queue at 0x10b5721e1dd8 maxsize=0>
>


(src/dienstbot/main.py:25)



repr(res) (133) = "<Task pending coro=<MessageLoop.run_forever() running at /home/tom/src/dienstbot/lib/python3.6/site-packages/telepot/aio/loop.py:73>>"

(src/dienstbot/main.py:158)



self = __main__.FonaSMS instance
<	
	id: 18367399796352
	
	path: src/dienstbot/main.py
	
	Ancestry:
		object
	
	__str__:
		<__main__.FonaSMS object at 0x10b47e571e80>
>


(src/dienstbot/main.py:108)



__main__ - 144.3 ms
  start: 1497462672.2898545 (src/dienstbot/main.py:116)
  stop: 1497462672.4341233

********** pid 27247: event loop running, press ctrl-c to interrupt. ***********
(src/dienstbot/main.py:163)

is a little hard to read. i suggest to unify the blank lines and in addition allow to disable them at all. regards

make pout.b a context manager

so you can do something like:

with pout.b():
    pout.v(a, b, c)

and it will box the pout.v() call by doing a start and stop pout.b() call:

********************************************************************************

a = 1

b = 2

c = 3

(file.py:M)

********************************************************************************
(file.py:N)

printing file is wrong

# file1.py

from file2 import String

s = String("foo")
pout.v(s)
# file2.py

class String(str):
    def __str__(self):
        pout.h()
        return self

when you run file1.py it will print:

here 6 (file1.py:6)

instead of:

here 5 (file2.py:5)

Printing python compatible code

Every once in a while I want to print a dict or something with pout and use that in actual python code, pout's dictionaries and lists are close to valid but not quite, which is annoying, I think I should add a py method that basically just does:

json.dumps(data, sort_keys=True, indent=4)

This will print valid dicts and lists and stuff, other things would have to be used for classes and the like (or an error raised).

maybe a problem?

So i've noticed that one of my files keeps refreshing if pout prints out unicode, after running the test vim will ask for the file with the pout.v() command to be refreshed because the file has changed, this might be because of 233c5ba but I'm not sure. I just wanted to get this down in case it is a thing

I had recently completely rebuilt my box, which installed 0.6.3.

Break each pout function into a supporting class

Now that all the actual string outputting code of all the values (see #32) has been broken out into specific supporting classes, and all the calling and parsing has also been broken out into their own classes it would be great to have like a V class that would be the backend for pout.v() and a T class that would handle pout.t() etc.

This would make it easier to override and customize functionality and keep everything contained to what applies to it instead of the previous solution of a monolithic Pout class.

pout.i()

print info about an object including all it's classes and ancestry

see also help(class).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.