Emacs interactive Python mode delays evaluation [duplicate] - python

I'm using Python 3.3 and Emacs 23.4 on Windows 7. I'm getting some odd behaviour when using python-shell. If I type in a command that produces some sort of output I get the result immediately on the next line. If the Python statement I've entered causes an error however, no output is shown. When I type in the next Python statement and hit enter, the error message for the previous line will be displayed.
For example when I'm processing some command line arguments:
>>> args
Namespace(templatedir=None, xmldir=None)
>>> args.bobbins
>>> args.templatedir
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Namespace' object has no attribute 'bobbins'
>>>
The first statement prints out the value of the args variable.
The second statement should print out an error message but nothing is printed.
The third statement is correct but actually prints out the error from the second statement.
Does anybody have any idea what's wrong with my Python / Emacs setup?

This was a bug in Python, and was fixed.

Related

Unexpected line given when Python interpreter reports exception [duplicate]

This question already has an answer here:
Why does Python read from the current directory when printing a traceback?
(1 answer)
Closed 3 years ago.
When the Python interpreter reports an error/exception (I'm just going to say "error" to refer to both of these from now on), it prints the line number and contents of the line that caused the error.
Interestingly, if you have a long-running Python script which causes an error and change the .py file while the script is running, then the interpreter can report an incorrect line as raising the error, based on the changed contents of the .py file.
MWE:
sample.py
from time import sleep
for i in range(10):
print(i)
sleep(1)
raise Exception("foo", "bar")
This script runs for 10 seconds, then raises an exception.
sample2.py
from time import sleep
for i in range(10):
print(i)
sleep(1)
"""
This
is
just
some
filler
to
demonstrate
the
behavior
"""
raise Exception("foo", "bar")
This file is identical to sample.py except that it has some junk between the end of the loop and the line raises the following exception:
Traceback (most recent call last):
File "sample.py", line 7, in <module>
Exception: ('foo', 'bar')
What I Did
python3 sample.py
In a second terminal window, mv sample.py sample.py.bak && cp sample2.py sample.py before sample.py finishes execution
Expected Behavior
The interpreter reports the following:
Traceback (most recent call last):
File "sample.py", line 7, in <module>
Exception: ('foo', 'bar')
Here, the interpreter reports that there was an exception on line 7 of sample.py and prints the Exception.
Actual Behavior
The interpreter reports the following:
Traceback (most recent call last):
File "sample.py", line 7, in <module>
"""
Exception: ('foo', 'bar')
Here, the interpreter also reports """ when it reports the exception.
It seems to be looking in the file on disk to find this information, rather than the file loaded into memory to run the program.
Source of my Confusion
The following is my mental model for what happens when I run python3 sample.py:
The interpreter loads the contents of sample.py into memory
The interpreter performs lexical analysis, semantic analysis, code generation, etc. to produce machine code
The generated code is sent to the CPU and executed
If an error is raised, the interpreter consults the in-memory representation of the source code to produce an error message
Clearly, there is a flaw in my mental model.
What I want to know:
Why does the Python interpreter consult the file on disk to generate error message, rather than looking in memory?
Is there some other flaw in my understanding of what the interpreter is doing?
As per the answer linked by #b_c,
Python doesn't keep track of what source code corresponds to any compiled bytecode. It might not even read that source code until it needs to print a traceback.
[...]
When Python needs to print a traceback, that's when it tries to find source code corresponding to all the stack frames involved. The file name and line number you see in the stack trace are all Python has to go on
[...]
The default sys.excepthook goes through the native call PyErr_Display, which eventually winds up using _Py_DisplaySourceLine to display individual source lines. _Py_DisplaySourceLine unconditionally tries to find the file in the current working directory (for some reason - misguided optimization?), then calls _Py_FindSourceFile to search sys.path for a file matching that name if the working directory didn't have it.

How to redirect Python Syntax Error into a textbox in MFC or other GUI framwork?

I embed Python into my GUI application, when the script throws syntax errors, I want to redirect the error message into a textbox, so I can know where the error is.
My codes is very simple:
Py_Initialize()
PyRun_SimpleString( "execfile('my.py')" );
Py_Finalize();
If the file contains syntax error, it may looks like:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "my.py", line 3, in <module>
app=everedit.Ap
AttributeError: 'module' object has no attribute 'Ap'
The above messages can be seen in a console window, but now I want to cache these messages in a GUI window.
A GUI window don't have a console. I want to output such messages into a text box.
Please note that I embed Python into C++, I want to cache Python's Syntax Error in C++.
As the documentation for PyRun_SimpleString clearly says:
Returns 0 on success or -1 if an exception was raised. If there was an error, there is no way to get the exception information.
So, if you want to get the exception information, you have to use slightly lower-level functions.
Meanwhile, once you're using the right function, and it returns NULL or -1 to tell you an exception occurred, how do you get the exception information (and distinguish SyntaxError from other exceptions, for whatever reason you want to do that)?
There's a whole chapter in the C-API docs on Exception Handling. But briefly: You call PyErr_Occurred to get the type of the exception. Then you call PyErr_ExceptionMatches to check whether it's the type you want. If so, use PyErr_Fetch to get the value and traceback so you can format them yourself, or PyErr_Format to get a simple formatted string, or whatever else you want. Then you just extract the Unicode or ASCII bytes from the string and put them in your GUI window.
Use a try/catch block and the traceback module (docs).
import traceback
try:
PyParser_SimpleParseString(input())
except SyntaxError as e:
# There will always be one line, but we're better off still looping over the list
# To be extra safe!
for line in traceback.format_exception_only(e.__class__, str(e)):
print(line) # Replace this with what write to the GUI
This will only give you the SyntaxError: x part, if you also want the traceback, use traceback.format_exception.

Emacs Python error delay

I'm using Python 3.3 and Emacs 23.4 on Windows 7. I'm getting some odd behaviour when using python-shell. If I type in a command that produces some sort of output I get the result immediately on the next line. If the Python statement I've entered causes an error however, no output is shown. When I type in the next Python statement and hit enter, the error message for the previous line will be displayed.
For example when I'm processing some command line arguments:
>>> args
Namespace(templatedir=None, xmldir=None)
>>> args.bobbins
>>> args.templatedir
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Namespace' object has no attribute 'bobbins'
>>>
The first statement prints out the value of the args variable.
The second statement should print out an error message but nothing is printed.
The third statement is correct but actually prints out the error from the second statement.
Does anybody have any idea what's wrong with my Python / Emacs setup?
This was a bug in Python, and was fixed.

Exiting from python Command Line

To exit from Python command line, I have to type exit(). If I type exit, it says
Use exit() or Ctrl-Z plus Return to exit
Usually when you type exit, you would want to exit the program. Why does the interpreter give me the above error when it knows I am trying to exit the command line? Why doesn't it just exit? I know it doesn't matter and its a silly question but I am curious.
This works for me, best way to come out of python prompt.
exit()
In my python interpreter exit is actually a string and not a function -- 'Use Ctrl-D (i.e. EOF) to exit.'. You can check on your interpreter by entering type(exit)
In active python what is happening is that exit is a function. If you do not call the function it will print out the string representation of the object. This is the default behaviour for any object returned. It's just that the designers thought people might try to type exit to exit the interpreter, so they made the string representation of the exit function a helpful message. You can check this behaviour by typing str(exit) or even print exit.
When you type exit in the command line, it finds the variable with that name and calls __repr__ (or __str__) on it. Usually, you'd get a result like:
<function exit at 0x00B97FB0>
But they decided to redefine that function for the exit object to display a helpful message instead. Whether or not that's a stupid behavior or not, is a subjective question, but one possible reason why it doesn't "just exit" is:
Suppose you're looking at some code in a debugger, for instance, and one of the objects references the exit function. When the debugger tries to call __repr__ on that object to display that function to you, the program suddenly stops! That would be really unexpected, and the measures to counter that might complicate things further (for instance, even if you limit that behavior to the command line, what if you try to print some object that have exit as an attribute?)
With Anaconda 4.5+ and Python 3.6+ on Windows use
Ctrl+Z
or
exit()
In some cases, you might have to use
Ctrl+Break
If your computer doesn't have Break key then see here.
I recommend you exit the Python interpreter with Ctrl-D. This is the old ASCII code for end-of-file or end-of-transmission.
This message is the __str__ attribute of exit
look at these examples :
1
>>> print exit
Use exit() or Ctrl-D (i.e. EOF) to exit
2
>>> exit.__str__()
'Use exit() or Ctrl-D (i.e. EOF) to exit'
3
>>> getattr(exit, '__str__')()
'Use exit() or Ctrl-D (i.e. EOF) to exit'
Because the interpreter is not a shell where you provide commands, it's - well - an interpreter. The things that you give to it are Python code.
The syntax of Python is such that exit, by itself, cannot possibly be anything other than a name for an object. Simply referring to an object can't actually do anything (except what the read-eval-print loop normally does; i.e. display a string representation of the object).
You can fix that.
Link PYTHONSTARTUP to a python file with the following
# Make exit work as expected
type(exit).__repr__ = type(exit).__call__
How does this work?
The python command line is a read-evaluate-print-loop, that is when you type text it will read that text, evaluate it, and eventually print the result.
When you type exit() it evaluates to a callable object of type site.Quitter and calls its __call__ function which exits the system. When you type exit it evaluates to the same callable object, without calling it the object is printed which in turn calls __repr__ on the object.
We can take advantage of this by linking __repr__ to __call__ and thus get the expected behavior of exiting the system even when we type exit without parentheses.
To exit from Python terminal, simply just do:
exit()
Please pay attention it's a function which called as most user mix it with exit without calling, but new Pyhton terminal show a message...
or as a shortcut, press:
Ctrl + D
on your keyboard...
If you stuck in python command line and none of above solutions worked for you,
try exit(2)
"exit" is a valid variable name that can be used in your Python program. You wouldn't want to exit the interpreter when you're just trying to see the value of that variable.
This UX in python:
$ python
Python 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
>>> ^D
File "<stdin>", line 1
♦
^
SyntaxError: invalid syntax
>>> exit
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'exit' is not defined
>>> quit
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'quit' is not defined
>>> exit()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'exit' is not defined
>>> quit()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'quit' is not defined

py-appscript expects arguments

I want to make a Python script to control VLC. VLC can be controlled through AppleScript and by using py-appscript I can run AppleScript code from Python.
Using AppleScript I can play/pause VLC by
tell application "VLC" to play
This equals to the following in py-appscript
app('VLC').play()
I should also be able to skip to next track by:
app('VLC').next()
But when doing so I get the following Python error:
Traceback (most recent call last):
File "vlclib.py", line 25, in <module>
app('VLC').next()
TypeError: next() takes exactly 2 arguments (1 given)
Does anyone know why I get this error? The above code should equal the following in AppleScript which works perfectly:
tell application "VLC" to next
From the appscript documentation:
Names that match Python keywords or names reserved by appscript have an underscore appended.
As next is a reserved keyword, you can fix this by running
app('VLC').next_()

Categories