'None' is not displayed as I expected in Python interactive mode - python

I thought the display in Python interactive mode was always equivalent to print(repr()), but this is not so for None. Is this a language feature or am I missing something? Thank you
>>> None
>>> print(repr(None))
None
>>>

It's a deliberate feature. If the python code that you run evaluates to exactly None then it is not displayed.
This is useful a lot of the time. For example, calling a function with a side effect may be useful, and such functions actually return None but you don't usually want to see the result.
For example, calling print() returns None, but you don't usually want to see it:
>>> print("hello")
hello
>>> y = print("hello")
hello
>>> y
>>> print(y)
None

Yes, this behaviour is intentional.
From the Python docs
7.1. Expression statements
Expression statements are used (mostly interactively) to compute and
write a value, or (usually) to call a procedure (a function that
returns no meaningful result; in Python, procedures return the value
None). Other uses of expression statements are allowed and
occasionally useful. The syntax for an expression statement is:
expression_stmt ::= starred_expression
An expression statement evaluates the expression list (which may be a
single expression).
In interactive mode, if the value is not None, it is converted to a
string using the built-in repr() function and the resulting string
is written to standard output on a line by itself (except if the
result is None, so that procedure calls do not cause any output.)

In Python, a function that does not return anything but is called only for its side effects actually returns None. As such functions are common enough, Python interactive interpreter does not print anything in that case. By extension, it does not print anything when the interactive expression evaluates to None, even if it is not a function call.
If can be misleading for beginners because you have
>>> a = 1
>>> a
1
>>>
but
>>> a = None
>>> a
>>>
but is is indeed by design

None represents the absence of a value, but that absence can be observed. Because it represents something in Python, its __repr__ cannot possibly return nothing; None is not nothing.
The outcome is deliberate. If for example a function returns None (similar to having no return statement), the return value of a call to such function does not get shown in the console, so for example print(None) does not print None twice, as the function print equally returns None.
On a side note, print(repr()) will raise a TypeError in Python.

Related

The None Value/Code in Automate the Boring Stuff

The text says the following:
In Python there is a value called None, which represents the absence of a value. None is the only value of the NoneType data type. (Other programming languages might call this value null, nil, or undefined.) Just like the Boolean True and False values, None must be typed with a capital N.
This value-without-a-value can be helpful when you need to store some-thing that won’t be confused for a real value in a variable. One place where None is used is as the return value of print(). The print() function displays text on the screen, but it doesn’t need to return anything in the same way len() or input() does. But since all function calls need to evaluate to a return value, print() returns None. To see this in action, enter the following into the interactive shell:
>>> spam = print('Hello!')
Hello!
>>> None == spam
True
Behind the scenes, Python adds return None to the end of any function definition with no return statement. This is similar to how a while or for loop implicitly ends with a continue statement. Also, if you use a return statement without a value (that is, just the return keyword by itself), then None is returned.
I think I understand what None is, but I am not understanding the code. Why is it that spam is then equal to None when it was assigned to be print('Hello!')? When I enter spam into the interactive shell immediately after the assignment it returns nothing. I get a feeling it is because the argument Hello! is immediately forgotten when print() is called and returns a value, but if I have defined spam to be the print() function with the argument Hello! passed through should it not always return Hello!?
To add to the comments and be more clear, your print() function printed 'Hello!' to the screen and returned None to the program. Printing and returning are not the same thing--printing is for the user, returning is for the program. The print goes to the screen only and (usually) cannot be further used by the program. The returned value can be stored in a variable, such as spam, and used further.
The distinction between printing and returning is important enough that the Python standard is that if a function prints something it should not return any value other than None, and if the function returns a value it should not print anything. This standard is not followed by many other languages (most notoriously C) and is not consistently followed in Python, but this distinction does help the clarity of Python. If you want to study this concept further, do a search on "side effects" in programming.
You are assigning spam to the print() function which doesn't return anything, aka None

print function not printing appropriate output using eval

I am getting 2 different outputs using 2 similar commands:
>>> inp = 'print("hi")'
>>> print(eval(inp))
hi
None
>>> eval(inp)
hi
How to I make print(eval(inp)) print just 'hi'? Why is None printing as well?
So here's what happens when you do print(eval('print("hi")')):
eval() is called, with the argument 'print("hi")'
Accordingly, the code print("hi") is executed
"hi" is printed to the console
Having finished executing, print() returns None.
Having executed the code 'print("hi")', the eval() function records the return call of that function. Which was None.
Accordingly, eval() returns None, since that was the result of the code it ran.
The outer print() call is supposed to print whatever the eval() function returned. Now it looks like print(None).
None is printed to console.
tl;dr, print() is called two different times. Thus, two different things are printed: "hi" the first time, and None the second time.
If all you want is to print "hi", you can just do eval('print("hi")') - or you could do print(eval("hi")), since in this case eval() would return "hi" and that's what would be printed. In either of those cases you would only ever be executing one print statement.
Though, in general, please do not use eval() for anything. It's notoriously risky, prone to errors that can completely break your program, and there's nothing you can do with it that you can't do with the code you'd put inside it. The only feasible reason for using eval() would be to respond dynamically to user-generated code, which is a terrible idea because it allows code injections. The user shouldn't be able to do that.

Why Python datatypes behave like this in Python prompt?

While messing around with python in the terminal I noticed something strange. If you enter an expression such as 1+2*3, the terminal will output 7, which is strange as this shouldn't print anything but it does. But then if you use a function such as print("hello world"), it will output hello world, and not None, which is what print returns. Also, typing True outputs True, and False outputs False, but typing None does not output anything. How does python decide when to output a value?
Exactly what happens when you evaluate an expression is determined by sys.displayhook. From the docs:
sys.displayhook(value)
If value is not None, this function prints it to sys.stdout, and saves it in __builtin__._.
sys.displayhook is called on the result of evaluating an expression entered in an interactive Python session. The display of these values can be customized by assigning another one-argument function to sys.displayhook.
Example of a simple override which takes away the None special case:
>>> def new_hook(x):
... print(repr(x))
...
>>> sys.displayhook = new_hook
>>> 3
3
>>> None
None
What you see is a Python REPL (Read-Evaluate-Print-Loop).
Most of the REPLs (including Python's REPL) will use an online parser: a parser that builds an expression tree. From the moment the expression tree is built, the REPL will evaluate it (this can be a function defintion, in which case the function is parsed and analyzed). After evaluating, the REPL will obtain the result and inspect the result*. If it is None, the result is not printed. The same happens with assignments by the way.
For example:
>>> None # None is not printed
>>> a = 2 # assignments are not printed
>>>
In case the result is not None, then it will call the repr(..) builtin method, and thus print the textual representation of the result.
The python session in the terminal is known as REPL, or Read-Evaluate-Print-Loop, which takes in input, evaluates it and returns the result. Check out the wikipedia page.

No return statement but still returning None

My function is just to modify a list.However, I don't want it to return anything not even 'None' and yet it returns 'None'. Is there a way to fix this?
TL;DR: No, there is not a meaningful way around default return of None in Python.
In Python, returning an implied None is the closest you can do to "return nothing". This is different to e.g. C where a void function declaration would prevent assignment to a variable. This behaviour is part of the Python language for consistency, because
x = MyFunc()
must define and store some value in x. Similarly, uses such as
OtherFunc( 1, 2, MyFunc() )
or
[ 1, 2, 3, MyFunc() ]
or
MyFunc() * 3
All need to have some behaviour. With an implied return value of None, these issues are solved in a particular way in Python.
It doesn't have to be this way - in principle if someone were to re-design this part of Python there could be a few different self-consistent approaches - for instance Python could have some special value that could only be returned from function calls and if it was found to be inside any other expression that could raise an error. Worth noting that in some cases, such as 3 * MyFunc(), a return value of None will raise an error in this way - but you cannot rely on that happening immediately in all possible unwanted scenarios based on the function definition.
However, Python returns implicit None. Changing this would affect any code/libraries that rely on the behaviour in a global way, or add awkward context-parsing requirements to the language because the feature necessarily would need to work both inside function definitions and where those functions were used.

Is there a string `s` such that eval(repr(s)) leads to arbitrary code execution?

I found similar code somewhere:
USER_CONTROLLED = 'a'
open("settings.py", "w").write("USER_CONTROLLED = %s" % eval(repr(a)))
And in another file:
import settings
x = settings.USER_CONTROLLED * [0]
Is this a security vulnerability?
In contrast to what you were told on IRC, there definitely is an x that makes eval(repr(x)) dangerous, so saying it just like that without any restrictions is wrong too.
Imagine a custom object that implements __repr__ differently. The documentation says on __repr__ that it “should look like a valid Python expression that could be used to recreate an object with the same value”. But there is simply nothing that can possibly enforce this guideline.
So instead, we could create a class that has a custom __repr__ that returns a string which when evaluated runs arbitrary code. For example:
class MyObj:
def __repr__ (self):
return "__import__('urllib.request').request.urlopen('http://example.com').read()"
Calling repr() on an object of that type shows that it returns a string that can surely be evaluated:
>>> repr(MyObj())
"__import__('urllib.request').request.urlopen('http://example.com').read()"
Here, that would just involve making a request to example.com. But as you can see, we can import arbitrary modules here and run code with them. And that code can have any kind of side effects. So it’s definitely dangerous.
If we however limit that x to known types of which we know what calling repr() on them will do, then we can indeed say when it’s impossible to run arbitrary code with it. For example, if that x is a string, then the implementation of unicode_repr makes sure that everything is properly escaped and that evaluating the repr() of that object will always return a proper string (which even equals x) without any side effects.
So we should check for the type before evaluating it:
if type(a) is not str:
raise Exception('Only strings are allowed!')
something = eval(repr(a))
Note that we do not use isinstance here to do an inheritance-aware type check. Because I could absolutely make MyObj above inherit from str:
>>> x = MyObj()
>>> isinstance(x, str)
True
>>> type(x)
<class '__main__.MyObj'>
So you should really test against concrete types here.
Note that for strings, there is actually no reason to call eval(repr(x)) because as mentioned above, this will result in x itself. So you could just assign x directly.
Coming to your actual use case however, you do have a very big security problem here. You want to create a variable assignment and store that code in a Python file to be later run by an actual Python interpreter. So you should absolutely make sure that the right side of the assignment is not arbitrary code but actually the repr of a string:
>>> a = 'runMaliciousCode()'
>>> "USER_CONTROLLED = %s" % eval(repr(a))
'USER_CONTROLLED = runMaliciousCode()'
>>> "USER_CONTROLLED = %s" % repr(a)
"USER_CONTROLLED = 'runMaliciousCode()'"
As you can see, evaluating the repr() will put the actual content on the right side of the assignment (since it’s equivalent to "…" % a). But that can then lead to malicious code running when you import that file. So you should really just insert the repr of the string there, and completely forget about using eval altogether.

Categories