Paging stdout output in IPython - ipython

Is it possible in an (interactive) IPython session to pass the stdout output through a pager, like less? If so, how?
For example, in
In [1]: from some_module import function_that_prints_a_lot
In [2]: function_that_prints_a_lot()
... everything scrolls away ...
I would like to page through the stdout output of function_that_prints_a_lot.
Another example:
In [1]: %run script_that_prints_a_lot.py
I've looked through IPython magic commands but didn't find any solution.

As discussed in chat there is no simple way of doing this. Since the function prints the values, the only thing you can do is Capture output + Then page output. There are few issues on jupyter that you might be interested in
https://github.com/jupyter/notebook/issues/2049
https://github.com/ipython/ipython/issues/6516
Capturing output
Output capturing can be done multiple ways
1. Overload Print Method
import sys
data = ""
def myprint(value, *args, sep=' ', end='\n', file=sys.stdout, flush=False):
global data
current_text = value + " ".join(map(str, args)) + "\n"
data += current_text
original_print = print
print = myprint
def testing():
for i in range(1,1000):
print ("i =", i)
testing()
original_print("The output from testing function is", data)
2. Capture output using StringIO
from cStringIO import StringIO
import sys
class Capturing(list):
def __enter__(self):
self._stdout = sys.stdout
sys.stdout = self._stringio = StringIO()
return self
def __exit__(self, *args):
self.extend(self._stringio.getvalue().splitlines())
del self._stringio # free up some memory
sys.stdout = self._stdout
Usage:
with Capturing() as output:
do_something(my_object)
3. Capture output using redirect_stdout
import io
from contextlib import redirect_stdout
f = io.StringIO()
with redirect_stdout(f):
do_something(my_object)
out = f.getvalue()
4. Capture using %%capture magic command
Paging Output
You can use magin %page
%page -r <variablename>
https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-page
Or you can use Ipython code
from IPython.core import page
page.page(variable)
For more details refer to below
PS: Some helpful threads
How to capture stdout output from a Python function call?
How can I redirect print output of a function in python
https://github.com/ipython/ipython/wiki/Cookbook:-Sending-built-in-help-to-the-pager
overload print python

Using bits and pieces from various sources, but essentially it's from IPython's cookbook and Defining custom magics from IPython official documentation
In [1]: from IPython.core.magic import register_line_magic
In [2]: #register_line_magic
...: def my_pager(line):
...: "my line magic"
...: import io
...: from IPython.core import page
...: from contextlib import redirect_stdout
...: f = io.StringIO()
...: with redirect_stdout(f):
...: eval(line)
...: page.pager_page(f.getvalue())
...: del my_pager # don't pollute my namespace
In [3]: def pippo(): print('\n'.join(str(i)for i in range(80)))
In [4]: %my_pager pippo()
This approach has a serious drawback: if the function call that is the argument to %my_pager returns a value, said value is lost (no, %mypager result=print_and_return() won't work...)

Related

How to get user ID through mentioning Telegram bot python

I write code for Replit.com
i make a command /add_administrator that is, Ana must add the user ID of the user I mentioned to the file admins.json but after using the command the bot breaks What I understand the bot sees(/add_administrator)
(#user)ignore or not see
I would like to understand how to get the user id through a #mention
It will be in a different language full code :https://github.com/jonoto2/TeleBotPHP/blob/main/main.py
complete command code:
from webserver import keep_alive
import json
import random
import re
import os
import telebot
from telebot import types
#from telegram.ext import Updater
bot = telebot.TeleBot(os.environ['TOKEN'], parse_mode="HTML")
#bot.message_handler(commands=['add_adm'])
def add_adm(message):
# Check if user is admin
if is_admin(int(message.from_user.id)):
args = get_args(message.text)
# Check for args
if args and args[0].isdigit():
id = int(args[0])
with open('admins.json', "r") as jsonFile:
data = json.load(jsonFile)
if id not in data:
data.append(id)
with open("admins.json", "w") as jsonFile:
json.dump(data, jsonFile)
bot.reply_to(message, f"`{id}` Appointed as admin.")
else:
bot.reply_to(message,
'This user is already an administrator .')
else:
bot.reply_to(message, 'User is not found.')
else:
bot.reply_to(message, 'You are not an administrator .')
I have not tried anything because I do not understand how

How does Pytest figure out that the monkeypatch fixture is for monkeypatching?

Consider this simple example from pytest's docs
# contents of test_module.py with source code and the test
from pathlib import Path
def getssh():
"""Simple function to return expanded homedir ssh path."""
return Path.home() / ".ssh"
def test_getssh(monkeypatch):
# mocked return function to replace Path.home
# always return '/abc'
def mockreturn():
return Path("/abc")
# Application of the monkeypatch to replace Path.home
# with the behavior of mockreturn defined above.
monkeypatch.setattr(Path, "home", mockreturn)
# Calling getssh() will use mockreturn in place of Path.home
# for this test with the monkeypatch.
x = getssh()
assert x == Path("/abc/.ssh")
How does Pytest figure out that the param monkeypatch is the one for monkeypatching?

Python subprocess.call() not working with >> operator

I'm trying to write a program that automatically sets up python shell scripts for me. Heres the code:
#!/usr/bin/env python3
import click
import subprocess
#click.command()
#click.argument('name')
def foo(name):
subprocess.call("cd ~/bin", shell=True)
subprocess.call(["touch", name])
subprocess.call(["echo", "'#!/usr/bin/env python3'", ">>", name])
subprocess.call(["chmod", "+x", name])
if __name__ == '__main__':
foo()
When it runs this is the output I get:
'#!/usr/bin/env python3' >> foo
A better way to approach this problem is to use the built-in Python libraries for creating files so that you can catch the exceptions easier. I've made a simple outline for you, but you should add some error checking.
import click
import os
import stat
#click.command()
#click.argument('name')
def foo(name):
file_to_create = os.path.expanduser("~/bin/") + name
with open(file_to_create, 'w') as file:
file.write("#!/usr/bin/env python3\n")
file_stats = os.stat(file_to_create)
os.chmod(file_to_create, file_stats.st_mode | stat.S_IEXEC) # equivalent of 'chmod +x'
if __name__ == '__main__':
foo()

environment variables using subprocess.check_output Python

I'm trying to do some basic module setups on my server using Python. Its a bit difficult as I have no access to the internet.
This is my code
import sys
import os
from subprocess import CalledProcessError, STDOUT, check_output
def run_in_path(command, dir_path, env_var=''):
env_var = os.environ["PATH"] = os.environ["PATH"] + env_var
print(env_var)
try:
p = check_output(command, cwd=dir_path, stderr=STDOUT)
except CalledProcessError as e:
sys.stderr.write(e.output.decode("utf-8"))
sys.stderr.flush()
return e.returncode
else:
return 0
def main():
requests_install = run_in_path('python setup.py build',
'D:\installed_software\python modules\kennethreitz-requests-e95e173')
SQL_install = run_in_path('python setup.py install', # install SQL module pypyodbc
'D:\installed_software\python modules\pypyodbc-1.3.3\pypyodbc-1.3.3')
setup_tools = run_in_path('python setup.py install', # install setup tools
'D:\installed_software\python modules\setuptools-17.1.1')
psycopg2 = run_in_path('easy_install psycopg2-2.6.1.win-amd64-py3.3-pg9.4.4-release', # install setup tools
'D:\installed_software\python modules', ';C:\srv_apps\Python33\Scripts\easy_install.exe')
print('setup complete')
if __name__ == "__main__":
sys.exit(main())
now it gets tricky when i start trying to use easy install. It appears my env variables are not being used by my subprocess.check_output call
File "C:\srv_apps\Python33\lib\subprocess.py", line 1110, in _execute_child
raise WindowsError(*e.args)
FileNotFoundError: [WinError 2] The system cannot find the file specified
I don't want to have to upgrade to 3.4 where easy install is installed by default because my other modules are not supported on 3.4. My main challenge is the subprocess.check_call method does not take environment variables as an input and im wary of trying to use Popen() as I have never really got it to work successfully in the past. Any help would be greatly appreciated.
PATH should contain directories e.g., r'C:\Python33\Scripts', not files such as: r'C:\Python33\Scripts\easy_install.exe'
Don't hardcode utf-8 for an arbitrary command, you could enable text mode using universal_newlines parameter (not tested):
#!/usr/bin/env python3
import locale
import sys
from subprocess import CalledProcessError, STDOUT, check_output
def run(command, *, cwd=None, env=None):
try:
ignored = check_output(command, cwd=cwd, env=env,
stderr=STDOUT,
universal_newlines=True)
except CalledProcessError as e:
sys.stderr.write(e.output)
sys.stderr.flush()
return e.returncode
else:
return 0
Example:
import os
path_var = os.pathsep.join(os.environ.get('PATH', os.defpath), some_dir)
env = dict(os.environ, PATH=path_var)
run("some_command", cwd=some_path, env=env)
run("another_command", cwd=another_path, env=env)

directory issues with an argument parser (ipython)

import the necessary packages
from matplotlib import pyplot as plt
import numpy as np
import argparse
import cv2
# construct the argument parser and parse the arguments
**ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())**
# load the image and show it
image = cv2.imread(args["image"])
cv2.imshow("image", image)**
My error is:
usage: -c [-h] -i IMAGE
-c: error: argument **-i/--image is required**
If this is my current wd: C:\Users\Jeremy\Documents\IPython Notebooks
what is wrong? what should I be inputing for -i/--image?