A library that can print Python objects in human readable format

Overview

objprint

build coverage pypi support-version license commit

A library that can print Python objects in human readable format

Install

pip install objprint

Usage

op

Use op() (or objprint()) to print objects.

from objprint import op

class Position:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Player:
    def __init__(self):
        self.name = "Alice"
        self.age = 18
        self.items = ["axe", "armor"]
        self.coins = {"gold": 1, "silver": 33, "bronze": 57}
        self.position = Position(3, 5)

op(Player())
<Player 0x7fe44e1e3070
  .age = 18,
  .coins = {'bronze': 57, 'gold': 1, 'silver': 33},
  .items = ['axe', 'armor'],
  .name = 'Alice',
  .position = <Position
    .x = 3,
    .y = 5
  >
>

You can print multiple objects just like print, except op will print them in separate lines

op([1, 2], {'a': 1})
[1, 2]
{'a': 1}

add_objprint

If you want to use print() to print your object, you can also use the class decorator add_objprint to add __str__ method for your class.

from objprint import add_objprint

class Position:
    def __init__(self, x, y):
        self.x = x
        self.y = y

@add_objprint
class Player:
    def __init__(self):
        self.name = "Alice"
        self.age = 18
        self.items = ["axe", "armor"]
        self.coins = {"gold": 1, "silver": 33, "bronze": 57}
        self.position = Position(3, 5)

# This will print the same thing as above
print(Player())

objstr

If you want the str representation of the object, instead of printing it on the screen, you can use objstr function

from objprint import objstr

s = objstr(my_object)

objjson

objprint supports print objects to json to make it easier to serialze an object.

objjson returns a jsonifiable object that can be dumped with json.dumps

from objprint import objjson

json_obj = objjson(Player())

print(json.dumps(json_obj, indent=2))
{
  ".type": "Player",
  "name": "Alice",
  "age": 18,
  "items": [
    "axe",
    "armor"
  ],
  "coins": {
    "gold": 1,
    "silver": 33,
    "bronze": 57
  },
  "position": {
    ".type": "Position",
    "x": 3,
    "y": 5
  }
}

You can use op to print in json format directly with format="json". You can pass in argument for json.dumps

op(Player(), format="json", indent=2)

add_objprint also works with format="json"

@add_objprint(format="json", indent=2)
class Player:
    pass

include/exclude attributes

You can include/exclude attributes using regular expression so objprint will only print out the attributes you are interested in.

op(Player(), include=["name"])
<Player
  .name = 'Alice'
>
op(Player(), exclude=[".*s"])
<Player 0x7fe44e1e3070
  .name = 'Alice',
  .age = 18,
  .position = <Position
    .x = 3,
    .y = 5
  >
>

If you specify both include and exclude, it will do a inclusive check first, then filter out the attributes that match exclusive check.

include and exclude arguments work on objprint, objstr and @add_objprint.

config

objprint formats the output based on some configs

  • config_name(default_value) - this config's explanation
  • depth(100) - how deep objprint goes into nested data structures
  • indent(2) - the indentation
  • width(80) - the maximum width a data structure will be presented as a single line
  • elements(-1) - the maximum number of elements that will be displayed, -1 means no restriction
  • color(True) - whether to use colored scheme
  • skip_recursion(True) - whether skip printing recursive data, which would cause infinite recursion without depth constraint
  • honor_existing(True) - whether to use the existing user defined __repr__ or __str__ method

You can set the configs globally using config function

from objprint import config

config(indent=4)

Or you can do a one time config by passing the arguments into objprint function

from objprint import op

op(var, indent=4)

install

Maybe you don't want to import op in every single file that you want to use. You can use install to make it globally accessible

from objprint import install

# Now you can use op() in any file
install()

# You can specify a name for objprint()
install("my_print")
my_print(my_object)

Bugs/Requests

Please send bug reports and feature requests through github issue tracker.

License

Copyright Tian Gao, 2020-2021.

Distributed under the terms of the Apache 2.0 license.

Comments
  • 在面对继承自pydantic里BaseModel的实例时无法得到预期的输出

    在面对继承自pydantic里BaseModel的实例时无法得到预期的输出

    如题

    from pydantic import BaseModel
    from objprint import op
    
    
    class pyt_class(BaseModel):
        x: int
        y: int
    
    
    obj_test = pyt_class(x=0, y=1)
    
    op(obj_test)
    print(obj_test)
    

    他打印:

    x=0 y=1
    x=0 y=1
    

    希望后续更新能够支持! (B站码农高天的视频我是期期都看,期期都三连)

    opened by Sclock 3
  • Also print the actual expression whose value is being printed

    Also print the actual expression whose value is being printed

    The https://github.com/gruns/icecream lib has an useful feature where it also prints the expression. Please see the following example:

    d = {'key': {1: 'one'}}
    ic(d['key'][1])
    
    class klass():
        attr = 'yep'
    ic(klass.attr)
    

    It prints:

    ic| d['key'][1]: 'one'
    ic| klass.attr: 'yep'
    

    As you can see icecream lib also prints the expression d['key'][1]. Is it possible to add this feature? This is the only feature holding me back from switching to objprint.

    opened by riyadparvez 3
  • Duplicate output when op() argument wasn't an object.

    Duplicate output when op() argument wasn't an object.

    import hashlib op(hashlib) <module 'hashlib' from 'C:\Users\guojoan\AppData\Local\Programs\Python\Python310\lib\hashlib.py'> <module 'hashlib' from 'C:\Users\guojoan\AppData\Local\Programs\Python\Python310\lib\hashlib.py'>

    a = [] a.append(a) op(a) [[ ... ]] [[...]]

    and so on

    opened by CokeStudios 2
  • type 类创建问题

    type 类创建问题

    通过type 构建的 class 通过 op 正确打印,这个feature 能否实现?

    from objprint import op
    
    class Action:
        pass
    
    def Category(label):
        return type("MCategory", (Action,), {"label": label,
                                            "__type__": "category"})
    
    
    class ECategory(Action):
        def __init__(self,label):
            self.label = label
            self.__type__ = 'category'
    
    
    
    mm = Category('test')
    nn = ECategory('test')
    op(mm)
    op(nn)
    
    >> <class '__main__.MCategory'>
    >> <UCategory 0x1f2da7b2b00
    >>   .label = 'test'
    >> >
    
    
    opened by wuqingjing2010 2
  • 如何实现“增量”打印?

    如何实现“增量”打印?

    您好!我正在使用objprint跟踪迭代过程,代码大致如下:

    for i in range(i_max):
        obj.step()
        op(obj)
    

    已知obj中有些变量在执行step后是不发生改变的,在第二次到最后一次调用op时,是否能够不打印这些变量?也就是只打印发生了变化的变量?

    opened by Saltsmart 2
  • weird escaped characters in jupyter notebook's output

    weird escaped characters in jupyter notebook's output

    I used pyreadstat module to read a simple SAS file. the code goes like this in jupyter notebook

    import pyreadstat as pyrs
    from objprint import op
    
    sas_path = './test_sas/foo.sas7bdat'
    df, meta = pyrs.read_sas7bdat(sas_path, metadataonly=True)
    # just wanted to check out what meta contains 
    op(meta)
    

    the brief output of current cell seems normal

    Output exceeds the [size limit]. Open the full output data[ in a text editor]
    <metadata_container 0x1bcf4bfa3e0
      .column_labels = [
        'projectid',
        'project',
    ...
        'project': '$'
      },
      .variable_value_labels = {}
    >
    <pyreadstat._readstat_parser.metadata_container at 0x1bcf4bfa3e0>
    

    but after I clicked "in a text editor", the first lines look like this:

    <metadata_container 0x1bcf4bfa3e0
      .column_labels = [
        'projectid',
        'project',
    

    the weird characters actually look like small suqares contains 3 small letters ESC in the text editor.

    opened by Asuralf 2
  • 在面对Enum对象时,输出的结果不符合预期。

    在面对Enum对象时,输出的结果不符合预期。

    测试代码:

    from enum import Enum
    from objprint import op,add_objprint
    
    class temp_a(Enum):
        a = 1
    
    @add_objprint
    class temp_b(Enum):
        b = 1
    
    print("temp_a:\n",temp_a,"\n")
    
    print("temp_a.a:\n",temp_a.a,"\n")
    
    print("op_temp_a:")
    op(temp_a)
    print("\n")
    
    print("op_temp_a.a:")
    op(temp_a.a)
    print("\n")
    
    print("================================================================\n")
    
    print("temp_b:\n",temp_b,"\n")
    
    print("temp_b.b:\n",temp_b.b,"\n")
    
    print("op_temp_b:")
    op(temp_b)
    print("\n")
    
    print("op_temp_b.b:")
    op(temp_b.b)
    print("\n")
    

    输出:

    temp_a:
     <enum 'temp_a'> 
    
    temp_a.a:
     temp_a.a
    
    op_temp_a:
    <enum 'temp_a'>
    
    
    op_temp_a.a:
    temp_a.a
    
    
    ================================================================
    
    temp_b:
     <enum 'temp_b'>
    
    temp_b.b:
     <temp_b 0x24a740c2ee0
      .__objclass__ = <enum 'temp_b'>,
      ._name_ = 'b',
      ._value_ = 1
    >
    
    op_temp_b:
    <enum 'temp_b'>
    
    
    op_temp_b.b:
    <temp_b 0x24a740c2ee0
      .__objclass__ = <enum 'temp_b'>,
      ._name_ = 'b',
      ._value_ = 1
    >
    

    符合直觉的结果应该是:

    class temp_a(Enum):
        a = 1
    op(temp_a)
    

    输出:

     <temp_a 0xFFFFFFFF
      .__objclass__ = <enum 'temp_a'>,
      .temp_a.a = < xxxxxxx
          ._name_ = 'b',
          ._value_ = 1
      >
    >
    
    opened by Sclock 2
  • 大佬,objprint可以打印出函数的内容吗?类似于js中console.log()方法。

    大佬,objprint可以打印出函数的内容吗?类似于js中console.log()方法。

    //JavaScript function ad(a, b) {

    return a + b;
    

    }

    console.log(ad.toString())

    //输出 // function ad(a, b) { // // return a + b; // }

    //python def ad(a,b): return a+b print(ad)

    输出

    <function ad at 0x000002511B318550>

    opened by xuxiaobo-bobo 1
  • Change the output order of line number and arg name

    Change the output order of line number and arg name

    For the following example:

    from objprint import config, install, objjson, op
    
    config(line_number=True)
    config(arg_name=True)
    
    x = 1
    op(x)
    

    This is the output right now:

    x:
    <module> (/path/to/objprint-test.py:7)
    1
    

    What I think more intuitive is argument name followed by the value and the file and line number at the top. In this particular case:

    <module> (/path/to/objprint-test.py:7)
    x:
    1
    

    Any thoughts?

    opened by riyadparvez 1
  • question: how to use install()

    question: how to use install()

    I created two python file to play with the install() feature:

    temp1.py:

    from objprint import op, install
    
    # Now you can use op() in any file
    install()
    

    temp2.py:

    op("hello")
    

    But run the temp2.py, it throws error : NameError: name 'op' is not defined What is the correct usage of install() ? Thanks !

    opened by wwdok 1
  • 在打印链表的时候结构不是很清晰

    在打印链表的时候结构不是很清晰

    打印链表会输出

    <Node 0x18136a4bd30
      .next = <Node 0x18136a4b3d0
        .next = <Node 0x18136dd5750
          .next = <Node 0x18136dd5930
            .next = <Node 0x18136dd5810
              .next = <Node 0x18136dd5870
                .next = None,
                .value = 'node_5'
              >,
              .value = 'node_4'
            >,
            .value = 'node_3'
          >,
          .value = 'node_2'
        >,
        .value = 'node_1'
      >,
      .value = 'Head'
    >
    

    可以考虑在打印属性为对象的属性的时候缩进幅度大一些

    <Node 0x18136a4bd30
        .next = <Node 0x18136a4b3d0
                .next = <Node 0x18136dd5750
                        .next = <Node 0x18136dd5930
                                    .next = <Node 0x18136dd5810
                                            .next = <Node 0x18136dd5870
                                                    .next = None,
                                                    .value = 'node_5'
                                            >,
                                            .value = 'node_4'
                                    >,
                                    .value = 'node_3'
                        >,
                        .value = 'node_2'
                >,
                .value = 'node_1'
         >,
         .value = 'Head'
    >
    

    或者结构修改一下

    <Node 0x18136a4bd30 ->  .next = <Node 0x18136a4b3d0 ->  .next = <Node 0x18136dd5750 ->  .next = <Node 0x18136dd5930 ->  .next = <Node 0x18136dd5810 ->  .next = <Node 0x18136dd5870 ->  .next = None,
                                                                                                                                                                                            .value = 'node_5'
                                                                                                                                                                                            >,         
                                                                                                                                                            .value = 'node_4'
                                                                                                                                                            >,
                                                                                                                            .value = 'node_3'
                                                                                                                            >,
                                                                                            .value = 'node_2'
                                                                                            >,
                                                            .value = 'node_1'
                                                            >,
                            .value = 'Head'
                            >
    

    简单的建议,希望能优化一下!

    opened by Sclock 1
  • pydantic.BaseModel 对象无法正确打印

    pydantic.BaseModel 对象无法正确打印

    我在使用 pydantic + objprint,打印对象使用了 #52 中的方法,但程序在 op 处阻塞住。

    from objprint import op
    from pydantic import BaseModel
    
    
    class A(BaseModel):
        a: int
    
    
    obj = A(a=1)
    op(obj, honor_existing=False)
    
    opened by Eric-fuyc 2
  • Detect repl for returning objects

    Detect repl for returning objects

    Now op() returns the object it prints to make calling chain possible. But in repl, that will print two instances. We should fix that for a better user experience.

    opened by gaogaotiantian 0
Releases(0.2.2)
Owner
Author of VizTracer, watchpoints and objprint
GUPNet - Geometry Uncertainty Projection Network for Monocular 3D Object Detection

GUPNet This is the official implementation of "Geometry Uncertainty Projection Network for Monocular 3D Object Detection". citation If you find our wo

Yan Lu 103 Dec 28, 2022
TCPNet - Temporal-attentive-Covariance-Pooling-Networks-for-Video-Recognition

Temporal-attentive-Covariance-Pooling-Networks-for-Video-Recognition This is an implementation of TCPNet. Introduction For video recognition task, a g

Zilin Gao 21 Dec 08, 2022
Official repo for the work titled "SharinGAN: Combining Synthetic and Real Data for Unsupervised GeometryEstimation"

SharinGAN Official repo for the work titled "SharinGAN: Combining Synthetic and Real Data for Unsupervised GeometryEstimation" The official project we

Koutilya PNVR 23 Oct 19, 2022
PyTorch implementation of an end-to-end Handwritten Text Recognition (HTR) system based on attention encoder-decoder networks

AttentionHTR PyTorch implementation of an end-to-end Handwritten Text Recognition (HTR) system based on attention encoder-decoder networks. Scene Text

Dmitrijs Kass 31 Dec 22, 2022
Deeper DCGAN with AE stabilization

AEGeAN Deeper DCGAN with AE stabilization Parallel training of generative adversarial network as an autoencoder with dedicated losses for each stage.

Tyler Kvochick 36 Feb 17, 2022
Public repo for the ICCV2021-CVAMD paper "Is it Time to Replace CNNs with Transformers for Medical Images?"

Is it Time to Replace CNNs with Transformers for Medical Images? Accepted at ICCV-2021: Workshop on Computer Vision for Automated Medical Diagnosis (C

Christos Matsoukas 80 Dec 27, 2022
Pytorch implementation of CVPR2020 paper “VectorNet: Encoding HD Maps and Agent Dynamics from Vectorized Representation”

VectorNet Re-implementation This is the unofficial pytorch implementation of CVPR2020 paper "VectorNet: Encoding HD Maps and Agent Dynamics from Vecto

120 Jan 06, 2023
wgan, wgan2(improved, gp), infogan, and dcgan implementation in lasagne, keras, pytorch

Generative Adversarial Notebooks Collection of my Generative Adversarial Network implementations Most codes are for python3, most notebooks works on C

tjwei 1.5k Dec 16, 2022
Code for T-Few from "Few-Shot Parameter-Efficient Fine-Tuning is Better and Cheaper than In-Context Learning"

T-Few This repository contains the official code for the paper: "Few-Shot Parameter-Efficient Fine-Tuning is Better and Cheaper than In-Context Learni

220 Dec 31, 2022
kapre: Keras Audio Preprocessors

Kapre Keras Audio Preprocessors - compute STFT, ISTFT, Melspectrogram, and others on GPU real-time. Tested on Python 3.6 and 3.7 Why Kapre? vs. Pre-co

Keunwoo Choi 867 Dec 29, 2022
Text completion with Hugging Face and TensorFlow.js running on Node.js

Katana ML Text Completion 🤗 Description Runs with with Hugging Face DistilBERT and TensorFlow.js on Node.js distilbert-model - converter from Hugging

Katana ML 2 Nov 04, 2022
Unbiased Learning To Rank Algorithms (ULTRA)

This is an Unbiased Learning To Rank Algorithms (ULTRA) toolbox, which provides a codebase for experiments and research on learning to rank with human annotated or noisy labels.

71 Dec 01, 2022
The Most Efficient Temporal Difference Learning Framework for 2048

moporgic/TDL2048+ TDL2048+ is a highly optimized temporal difference (TD) learning framework for 2048. Features Many common methods related to 2048 ar

Hung Guei 5 Nov 23, 2022
HODEmu, is both an executable and a python library that is based on Ragagnin 2021 in prep.

HODEmu HODEmu, is both an executable and a python library that is based on Ragagnin 2021 in prep. and emulates satellite abundance as a function of co

Antonio Ragagnin 1 Oct 13, 2021
ParmeSan: Sanitizer-guided Greybox Fuzzing

ParmeSan: Sanitizer-guided Greybox Fuzzing ParmeSan is a sanitizer-guided greybox fuzzer based on Angora. Published Work USENIX Security 2020: ParmeSa

VUSec 158 Dec 31, 2022
A curated list of long-tailed recognition resources.

Awesome Long-tailed Recognition A curated list of long-tailed recognition and related resources. Please feel free to pull requests or open an issue to

Zhiwei ZHANG 542 Jan 01, 2023
FANet - Real-time Semantic Segmentation with Fast Attention

FANet Real-time Semantic Segmentation with Fast Attention Ping Hu, Federico Perazzi, Fabian Caba Heilbron, Oliver Wang, Zhe Lin, Kate Saenko , Stan Sc

Ping Hu 42 Nov 30, 2022
A Partition Filter Network for Joint Entity and Relation Extraction EMNLP 2021

EMNLP 2021 - A Partition Filter Network for Joint Entity and Relation Extraction

zhy 127 Jan 04, 2023
Rule Based Classification Project For Python

Rule-Based-Classification-Project (ENG) Business Problem: A game company wants to create new level-based customer definitions (personas) by using some

Deniz Can OĞUZ 4 Oct 29, 2022
[CVPR 2021] A Peek Into the Reasoning of Neural Networks: Interpreting with Structural Visual Concepts

Visual-Reasoning-eXplanation [CVPR 2021 A Peek Into the Reasoning of Neural Networks: Interpreting with Structural Visual Concepts] Project Page | Vid

Andy_Ge 54 Dec 21, 2022