tags:

views:

210

answers:

8

I should say I'm looking for a solution to the problem of viewing output that does not fit on your screen. For example, range(100) will show the last 30ish lines in your terminal of 30 height.

I am only looking to be nudged in the right direction and am curious how you guys have approached this problem.

What have you done when you run into a situation where you wish you could conveniently scroll through some large output?

Best Answer

Use the scrollback buffer on your terminal.

If you're using GNU Screen, it can be set with defscrollback 1000 or any other number in HOME/.screenrc.

Use Ctrl-a, [ to enter copy mode

j -    Move the cursor down by one line
k -    Move the cursor up by one line
C-u -  Scrolls a half page up.
C-b -  Scrolls a full page up.
C-d -  Scrolls a half page down.
C-f -  Scrolls the full page down.
G -    Moves to the specified line 

The best part is ? for reverse search, / for forward search while in copy mode.

Super convenient.

Thank you!


Original question:

What is the python equivalent of the bash less command?

LongString | less 

Is there something like that for python? I find myself thinking I could use it fairly often but just move on and find some other solution.

By "long things" I mean anything that generates more output lines than my screen. 1000 print messages, a dictionary, a large string, range(1000), etc.

My googlefu has failed.

A: 

It's easy to write your own:

def less(s, line_count = 5):
    lines = []
    for i, line in enumerate(s.split('\n'), 1):
        lines.append(line)
        if (i % line_count) == 0:
            yield '\n'.join(lines)
            lines = []

    if lines:
        yield '\n'.join(lines)
Chris B.
Hey Chris, thanks! I thought about a way or two to split various output but it seems like something so common that it would be built in. I was surprised I couldn't google it.
Yuji
+1  A: 

If you work in ipython you can issue shell commands within your interactive python session. That means that you just do

In [1]: less myfile.txt

I also really like being able to arrow up and down to get previous commands and getting the output from previous commands by doing something like

In [33]: print cos(Out[7]*pi/180)
procrastinate_later
Thanks for that! I love ipython and being able to use commands. I do use that frequently and love being able to edit files from within. My output would be in the interpreter, so no filenames. I suppose I could save the output as a file :P can I pipe in output to less directly?
Yuji
I haven't used the edit command in ipython much, and I'm not sure how you name your files. I tend to edit Python files with Eclipse or gedit, and use ipython when I want to inspect how some of my code is working interactively.
procrastinate_later
+4  A: 

Yes, there is a way and it is quite trivial, that's why not specifically described. Say you have long list and want to see just the beginning:

>>> lst = range(1000)   # let's make list of thousand elements
>>> lst[:100]           # i want to see just the first 100
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> lst[100:201]        # ok, now the 2nd hundred 
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200]
>>> lst[-100:]          # and now just the last 100, pretty please?
[900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999]

The same [] slicing works the same for strings. For dictionary you can cheat somehow, like using str() to convert it to string and then display with the same slicing :-)

Nas Banov
A: 

There's one fundamental difference between less run in a shell, and Python: Python is a programming language, less is a program.

Bash is aware of what the linecount is in the console, and less can query that (and a number of other things), Python on its own can't be, it's a language and it's agnostic to its environment (that's left to libraries).

On top of that, less obeys some of its own standards. Careted lines get moved to top, it feeds to termcap, it's conceptually part of the OS tools, and it's meant to send to output even if it hasn't finished reading the file.

You can write less in Python if you want, or run it from inside a python script, but its functionality is more (and too specific) than a single method of file should contain.

ThE_JacO
Thanks, I appreciate the answer. I should rephrase and say I'm looking for a solution to my problem of viewing output that's larger than my screen. So far, it seems I need to write my own that splits various output into chunks, but it seemed like something that would exist.
Yuji
+1  A: 

if your data is json serilizable then you can try

import simplejson
print simplejson.dumps({'shipping-line': {'price': '0.00', 'code': 'Local Pickup (Portland, OR)', 'title': 'Local Pickup (Portland, OR)'}}, indent=4)

Output will be look something like

{
    "shipping-line": {
        "price": "0.00", 
        "code": "Local Pickup (Portland, OR)", 
        "title": "Local Pickup (Portland, OR)"
    }
}

this is specifically used to debug and to see the actual content......in well readble format..

EDIT:

if your screen is limited to 25 lines..........

import simplejson
data = simplejson.dumps({'shipping-line': {'price': '0.00', 'code': 'Local Pickup (Portland, OR)', 'title': 'Local Pickup (Portland, OR)'}}, indent=4)

cnt = 0

for line in data.split('\n'):
    cnt+=1
    print line
    raw_input() if cnt%25==0 else None
Tumbleweed
Hey shah, thanks! but what if the output is 10x longer and won't fit my terminal? The output scrolls to the bottom. Is my solution only to slice it?
Yuji
check the edited answer.
Tumbleweed
+2  A: 

If you want to do this for an interactive python session, you should use a terminal emulation that allows you to scroll back up. I believe most of them do.

If you're using an actual terminal, or if you don't have a choice of terminal emulators, perhaps you can use GNU screen.

(If you're using Windows, you can change the screen buffer size to allow scrolling back up to 9999 lines).

And if you need this for the output of your program, you can try to use the curses module to implement scrolling yourself.

itsadok
This is sounding like a great solution! Facepalm! I just need to raise my scrollback buffer way up in screen. Ooohhh will try this tomorrow. Can't thank you enough.
Yuji
Raised my GNU Screen scrollback buffer to 10k : ) Can navigate up half page, full page, etc conveniently. Thanks for the answer itsadok! I will write about it in the hopes that others find it useful. It seems hard to ask this question without getting attacked for better coding practice, don't get in the situation in the first place, etc. You were supremely helpful.
Yuji
A: 

just for fun :o)

class Less(object):
    def __init__(self, num_lines):
        self.num_lines = num_lines
    def __ror__(self, other):
        s = str(other).split("\n")
        for i in range(0, len(s), self.num_lines):
            print "\n".join(s[i:i+self.num_lines])
            raw_input("Press <Enter> for more")

less=Less(num_lines=30)  
"\n".join(map(str,range(100))) | less
gnibbler
A: 

What have you done when you run into a situation where you wish you could conveniently > scroll through some large output?

  1. Don't create large output. Use functions to summarize or show selected details.

  2. Simplify the application to avoid creating large output in the first place.

  3. Focus what I'm looking at to avoid large output.

  4. Generally avoid large output.

It seems simpler to avoid large output than to fuss around trying to display something I never cared about in the first place.

S.Lott
I'm agree, S.Lott!!!
Tumbleweed
Hi S, thanks for that, but I'm specifically talking about those small situations where i DO run into large output. Normally, I know exactly what should be in a dictionary so large output isn't a problem. But if once every full moon, I'll be in a situation where I'm in python, and I pull up a database entry that has a large entry that I'd rather not go to PGSQL for.I wish you guys would help with the real issue, not suggest my issue is invalid.
Yuji
@Yuji: Sorry but you're missing the point. Your issue **is** invalid. You have Python. You can write code. So write code. Please write code to manipulate/summarize/filter/extract your data. Please just write code -- that's why you're using Python.
S.Lott
I'm sorry you don't seem to get my point: I asked what to do when you run into large output. You answered to not have large output in the first place. I completely agree, I stay away from it, but when you do run into a situation where some code you don't control spits out 100 print statements and want to see the first line, what do you do?It is not simpler to avoid large output as that would require time and effort modifying a foreign program when all I'm interested in is a glance at the output. I hope I'm making sense here. Not running into these situations is certainly ideal :)
Yuji
The solution is to raise the scrollback buffer in whatever terminal you're using and scroll up :P yay. zero coding, super convenient, and exactly the kind of answer I'm looking for. The answer to "what do you do when you wish you could scroll through some large output" is "scroll through the large output" :D Thank you all
Yuji
"some code you don't control" Doesn't make sense. Stop using it. Subclass it, or write your own version. You can see the source. You can fix the source. You don't have to endure other people's bad design. This is Python -- you can fix it.
S.Lott
I honestly have no idea why you're being so argumentative. I don't need to take a gun to a knife fight, I was looking for a solution that is as easy and convenient as possible: found it. Thanks!
Yuji
@Yuji: You keep arguing with my answer. I gave you an answer -- to which you keep posting arguments. You don't have to agree with my answer. You already picked another answer as the one you agree with. I cannot understand your problem. I'm arguing that your problem does not make sense to me. I have never had it. I cannot see how anyone could have it. You can continue arguing if you want; but you already accepted another answer.
S.Lott
Sorry to put that on you S. You're right, it's me arguing. I was assuming my point could be understood. Thank you for your time and help!
Yuji
@Yuji: Your point is understood. And you're looking in the wrong places. Looking for help from outside the core Python language misses the value of Python. You have a language that allows you to write good code. Use it. Filter, Summarize, Focus. Fix the bad software that dumps too much stuff. **Use The Language**.
S.Lott
I use the django ORM testing ideas in the interpreter, so I often have something like myblogpost.body. The large output in this case is not a mistake on my part or improper python (right?) I'm not saying it's right to read blog posts in the interpreter, but I find myself in these situations where I already have someobject in the interpreter, and pulling up someobject.thingtoread is faster than going to SQL or the web to get the same information. Is it still wrong to have a solution outside the language? I think the interpreter is hard to separate from the terminal, so it's not so far outside.
Yuji
@Yuji: "Is it still wrong to have a solution outside the language?". Yes.
S.Lott
@Yuji: I use the Django ORM every day (8 hours a day!) I have never had a problem viewing output. I have Python. I use Python. QueryResult objects are list-like and and I can use list programming techniques **in the interpreter**. Directly. Really. Every day. I can "slice" and "sort" and use "for" statements and everything. In the interpreter. Interactively.
S.Lott
For me, the less i know about the data, the faster scrolling is (3 keystrokes +1 per page). The more I know about it, the faster sorting/slicing is. Both have their place.As for the right/wrong of looking outside the language? We are essentially of different religions, and we can only walk away or kill each other. I'll take the former.
Yuji
"We are essentially of different religions, and we can only walk away or kill each other" Makes very little sense. Are you still arguing about my answer? Why?
S.Lott
The religion comment was a joke about how it's important to you to stay in python, while it's not to me. I'm trying to exit!
Yuji
@Yuji: I can't understand any of these comments. What point are you making? Can you summarize? Are you simple repeating that you don't like my answer? If so, why continue to repeat that you don't like my answer? What have I missed. You don't like my answer. I get it. What else is there? You couldn't find your scroll buffer settings. I get it. What else is there?
S.Lott
Hi S, I fail at communication :( I should really work on that. Well, thanks for putting up with me thus far!
Yuji
@Yuji: communicate what? What are you trying to communicate? Are you still trying to explain your preferred answer? Why? Why does it matter that I agree with anything? I don't think your problem in sensible. You can continue to explain it, but I can only see it as non-sensical. Why continue to pound away at this thread? What is your point? What point are you trying to make?
S.Lott