Python equivalent of PyErr_Print() - python

What is the Python API equivalent of PyErr_Print(), from the C interface?
I'm assuming a call in either the sys, or traceback modules, but can't find any functions therein that make calls to PyErr_Print().
Addendum
I'm after the Python call to get the same functionality as PyErr_PrintEx(), described as:
Print a standard traceback to sys.stderr and clear the error indicator.
That is I want to make the Python call that has this effect.

There's no Python function that's exactly equivalent to PyErr_PrintEx (the real name of PyErr_Print;-), including for example setting sys.last_traceback and friends (which are only supposed to be set to help a post-mortem debugging from the interactive interpreter for exceptions which have not been caught). What exact combination of functionality are you looking for?

Related

Different scope of custom exception type in doctest when run by PyCharm. Why?

I have a function raising a custom exception type. To my own annoyance my pedantic nature lets me want a docstring containing a doctest snippet:
# my_package/my_module.py
class Mayday(ValueError): pass
def raisins():
"""
>>> raisins()
Traceback (most recent call last):
...
my_module.Mayday: Yikes!
"""
raise Mayday('Yikes!')
# EOF, i.e. nothing calling doctest.testmethod() explicitly
Now, this works fine when run within my local PyCharm using an automatically created run configuration (Run 'Doctests in my_module'). It fails basically anywhere else, i.e. when invoking python -m pytest --doctest-modules (under various environments). The problem is the scope of the exception type which then prepends the package name:
Expected: ... my_module.Mayday: Yikes!
Got: ... my_package.my_module.Mayday: Yikes!
Interestingly calling raisins() within the PyCharm provided Python console (which means it should use the very same environment) yields an exception type including the package name and by this - in a way - contradicts itself.
There must be a difference in invoking doctest I am not aware of. What is it?
Like every good programmer I adapted the tests so everything is green now. +cough+ Still this is not really a satisfying solution. Is there a way to succeed both ways (maybe by a clever way to import within the docstring)?

How to inspect the type of REPL you're using?

There're many kinds of Python REPL, like the default REPL, ptpython, ipython, bpython, etc. Is there a way to inspect what current REPL is when I'm already in it?
A little background:
As you may have heard, I made pdir2 to generate pretty dir() printing. A challenge I'm facing is to make it compatible with those third-party REPLs, but first I need to know which REPL the program is running in.
Ok, finally found a simple but super reliable way: checking sys.modules.
A function you could copy and use.
import sys
def get_repl_type():
if any('ptpython' in key for key in sys.modules):
return 'PTPYTHON'
if any('bpython' in key for key in sys.modules):
return 'BPYTHON'
try:
__IPYTHON__
return 'IPYTHON'
except NameError:
return 'PYTHON'
Probably the best you can do is to look at sys.stdin and stdout and compare their types.
Maybe there are also ways for each interpreter to hook in custom completions or formatters.
You can try to find information from the call stack.
Those fancy REPLs use their startup script to initialize.
It's possible to run one REPL in another, so you need to traverse call stack from top to bottom until find a frame from REPL init script.

Call a ruby script from python, and return response

I am using python, and I want to call a Ruby function (i.e. in a similar manner to how i would call a python function), specifying function arguments, and then get back a returned value.
I have been searching around, and can see how to run ruby code e.g. using os.system, however can't seem to either:
call a specific function within the Ruby code, passing variables
Return the result of the function to Python.
e.g. I am looking to be able to do something similar to:
desired_response = ruby_function(variables)
where ruby_function is within a file called ruby_file, and the response is the result of running that function.
I don't know what is your output from ruby program but with os.startfile()you can run your ruby script.
Here's a more recent solution that i found and seems a lot smoother than having a third party tool to invoke this.
You can simply use the Python subprocess.
I ended up using it this way:
import subprocess
response = subprocess.run([f"{os.environ['YOUR_SCRIPT_PATH']}", first_variable_to_pass_to_script, second_variable])
Hope this helps!
###OLD ANSWER:
I found this article to be helpful!
http://sweetme.at/2014/03/14/a-simple-approach-to-execute-ruby-scripts-with-python/#:~:text=Execute%20the%20Ruby%20File%20from%20Naked.toolshed.shell%20import%20execute_rb,the%20Ruby%20code%20to%20the%20Python%20calling%20code.
You might need to use:
from Naked.toolshed.shell import execute_rb
success = execute_rb('testscript.rb')
to be able to handle your standard I/O error in Python rather than Ruby.
Original documentation: https://naked.readthedocs.io/toolshed_shell.html

Python redirect return statement to stdout

I am writing a Python interpreter and want to redirect the function's return values to stdout, like the Python Interpreter in Interactive Mode. Within this mode, when the user calls a function, its return value is printed on the screen. The same occurs with expressions.
E.g.
>>> foo()
'Foo return value'
>>> 2+4
6
>>> print('Hello!')
'Hello!'
Changing the sys.stdout only affects the print function. How do I redirect the other expressions to stdout?
Thank you
First, the interactive mode does not print the return value from any function called. Instead, it prints the result of whatever expression the user typed in. If that's not a function call, it still gets printed. If it has 3 function calls in it, it still prints one result, not 3 lines. And so on.
So, trying to redirect function return values to stdout is the wrong thing to do.
What the interactive interpreter does is something sort of like this:
line = raw_input(sys.ps1)
_ = eval(line)
if _ is not None:
print repr(_)
(You may notice that you can change sys.ps1 from the interactive prompt to change what the prompt looks like, access _ to get the last value, etc.)
However, that's not what it really does. And that's not how you should go about this yourself either. If you try, you'll have to deal with complexities like keeping your own globals separate from the user's, handling statements as well as expressions, handling multi-line statements and expressions (doing raw_input(sys.ps2) is easy, but how do you know when to do that?), interacting properly with readline and rlcomplete, etc.
There's a section of the documentation called Custom Python Interpreters which explains the easy way to do this:
The modules described in this chapter allow writing interfaces similar to Python’s interactive interpreter. If you want a Python interpreter that supports some special feature in addition to the Python language, you should look at the code module.
And code:
… provides facilities to implement read-eval-print loops in Python. Two classes and convenience functions are included which can be used to build applications which provide an interactive interpreter prompt.
The idea is that you let Python do all the hard stuff, up to whatever level you want to take over, and then you just write the part on top of that.
You may want to look at the source for IDLE, ipython, bpython, etc. for ideas.
Instead of using exec() to run the user input, try eval():
retval = eval(user_input)
sys.stdout.write(repr(retval) + "\n")

How to access the calling source line from interactive shell

I want to make a function that can determine the source code of how it was called. I'm aware of how to do this generally with the inspect module. For example, this question, works well and provides my desired output in the lines variable as shown below:
def hello(x):
frame,filename,line_number,function_name,lines,index=\
inspect.getouterframes(inspect.currentframe())[1]
print(frame,filename,line_number,function_name,lines,index)
The problem is that this solution doesn't work in an interactive command line session. For example, from a command line, the result looks like:
>>> y = hello(7)
(<frame object at 0x01ECA9E8>, '<stdin>', 1, '<module>', None, None)
The problem is that the source file is '<stdin>', so the lines variable is None. How can I access the calling line to find the result containing the string y = hello(7) during an interactive session?
It may not be possible, as #abarnert says. There are at least partial workarounds, however.
Getting source code lines isn't the biggest problem; modules like readline keep track of them. Interactive Python and iPython expose their lines slightly differently (sigh), but that too can be equalized. (My show package, for example, does this; its linecacher module puts a veneer on to equalize source access for normal Python and the different interactive flavors.)
The bigger problem is that, even once you have the source code, inspect doesn't provide legitimate line numbers (e.g. inspect.currentframe().f_back.f_lineno works great in normal code, but gives values like 1 or the point of the call in <stdin> when called interactively.)
But I'm not quite ready to call it impossible. Based on tracebacks generated by interactive Python and iPython, it appears that there may be sufficient information available to reconstruct "where did this call come from?" How much effort that would take, and how robust the answers would be...those are open questions.

Categories