Multiline script in a python command line argument - python

I am trying to invoke python from within an arch linux PKGBUILD script:
python -c "from module import func; func()"
The func raises an exception, which is expected behavior but causes the script to fail.
Catching the exception like this does not work:
python -c "from module import func; try: func(); except ValueError: pass"
It seems there is no way to put try/except statements into a single line (Python: try statement in a single line).
Is there another way to ignore the exception or the fact that python returns with an error?
A solution that does not require additional scripts or other files would be most welcome :)

Strings in shell can contain embedded newlines:
python -c 'from module import func
try:
func()
except ValueError:
pass
'
Note that this presents a challenge if the Python to run contains a mix of quotation marks, which would require some contortions to ensure they are all escaped properly. In that case, a here document would be more appropriate then the -c option (although this presents its own issues if the code to run needs to read from standard input.)
python << EOF
from module import func
try:
func()
except ValueError:
pass
EOF

You can also enter the script to be executed interactively like this:
$ cat -- | python
<code here>
<code here>
<code here>
<press Ctrl-D>
and Python will run what you entered, for example:
~$ cat -- | python
from module import func
try:
func()
except ValueError:
pass
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named module

Related

how can i redirect my error message from console to file in Python [duplicate]

This question already has an answer here:
redirect_stderr does not work (Python 3.5)
(1 answer)
Closed last year.
I need to redirect my error message from the console to a file. For this example, I need to insert the error message into a file:
Traceback (most recent call last):
File "C:/Users/", line 5, in <module>
1/0
ZeroDivisionError: division by zero"
I have already tried to do something like this:
from contextlib import redirect_stdout
with open('error.txt', 'w') as f:
with redirect_stdout(f):
1/0
print('here is my error')
If you plan to run your script in console itself, you can just use the bash's ">" operator to send the input of your command (in this situation : your script) in a file just like this :
python ./yourScript > ./outputFile
Everything that your script will print will go in the specified file.
You need to catch the error or your application will fail:
from contextlib import redirect_stdout
with open('error.txt', 'w') as f:
try:
1/0
except ZeroDivisionError as e:
f.write(e)
Note: This assumes you're using Bash. I see that you are using Windows, so it's likely that you aren't using Bash. But from what I've read, this should still be applicable if you are using Cmd.exe, it's just that the syntax might be slightly different.
I think it's better to handle error message output outside of your script. Your script should attempt to do the "happy path" work and print an error to stderr if something goes wrong. This is what should happen by default in every programming language. Python gets this right.
Here is an example script:
print("Dividing by 0 now, I sure hope this works!")
1/0
print("Holy cow, it worked!")
If I run this script, the first line prints to stdout, and then the ZeroDivisionError output prints to stderr:
$ python /tmp/script.py
Dividing by 0 now, I sure hope this works!
Traceback (most recent call last):
File "/tmp/script.py", line 3, in <module>
1/0
ZeroDivisionError: integer division or modulo by zero
If I want to run the script and collect any error output in a file, I can use redirection in my shell when I run the command:
$ python /tmp/script.py 2> /tmp/errors.txt
Dividing by 0 now, I sure hope this works!
$ cat /tmp/errors.txt
Traceback (most recent call last):
File "/tmp/script.py", line 3, in <module>
1/0
ZeroDivisionError: integer division or modulo by zero

how to pass variables from GDB to invoked python interpeter

From some version of GDB (I guess 7 or so) it is possible to invoke python from GDB in interactive or non interactive way.
Here is some example:
(gdb) python print("gdb".capitalize())
Gdb
(gdb)
Is it possible to pass variables from used in GDB into Python? I've tried something like this but with no luck:
Try to pass C variable named c_variable
(gdb) python print(c_variable.capitalize())
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name 'c_variable' is not defined
Error while executing Python code.
Try to pass GDB's variable named $1
(gdb) python print($1.capitalize())
File "<string>", line 1
print($1.capitalize())
^
SyntaxError: invalid syntax
Error while executing Python code.
EDIT
Almost imediatelly after my question I've found this question passing c++ variables to python via gdb
So I've end up with following:
(gdb) whatis p_char
type = char *
(gdb) ptype p_char
type = char *
(gdb) p p_char
$1 = 0x8002004 "hello world"
(gdb) python x=str(gdb.parse_and_eval('p_char')); print(x.split(" "))
['0x8002004', '"hello', 'world"']
This is something that I can work with but I need to do some extra cleanup (remove quotes, address etc), is there any better way? And I still do not know if is possible to pass $1.
Try to pass C variable named c_variable
Try to pass GDB's variable named $1
py print(gdb.parse_and_eval("c_variable"))
py print(gdb.parse_and_eval("$1"))
If you want to work with Python and GDB I would highly recommend reading this. Of special interest to you would be this page that includes parse_and_eval as well as this page on values.
The gdb.parse_and_eval function returns a gdb.Value object. For values that are strings you can use the string method, so:
(gdb) python print(gdb.parse_and_eval("string_var").string())
Hello World
(gdb) python print(gdb.parse_and_eval("string_var").string()[::-1])
dlroW olleH

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 can I redirect only part of a stream?

I'm using Python on bash on Linux. I would like to be able to suppress error messages from a particular module, but keep other error messages. An example would probably be the most efficient way to convey what I want:
File: module.py
import sys
sys.stderr.write('Undesired output.\n')
File: script.py
import module
import sys
sys.stderr.write('Desired output.\n')
sys.stdout.write('Desired output.\n')
x = int('a')
Output of running script.py:
$ python script.py
Undesired output.
Desired output.
Desired output.
Traceback (most recent call last):
File "script.py", line 6, in <module>
x = int('a')
ValueError: invalid literal for int() with base 10: 'a'
Desired output of running script.py:
$ python script.py
Desired output.
Desired output.
Traceback (most recent call last):
File "script.py", line 6, in <module>
x = int('a')
ValueError: invalid literal for int() with base 10: 'a'
I cannot modify module.py, but I must use it. I've tried all kinds of redirects, and opening new file descriptors, but I can't seem to change the file descriptors of the calling shell from within python, so
$ python script.py 2>/dev/null
Desired output.
kills ALL stderr output. Since I know that the module is causing the undesired message, I know exactly which point I want to stop redirecting stderr to /dev/null and start redirecting it to &1, but I can't seem to be able to do it from within Python.
Any advice is much appreciated!
There is an example here in the accepted answer that might help you
Temporarily Redirect stdout/stderr
but in your case, it assumes that you could do
import module
after
import sys
and after you've redirected stderr in your Python code. Like
import sys
... redirect code here
import module
... code to remove redirect
Don't know if that will break your desired functionality, beyond the redirects.
Also you're not supposed to stick import statements in the middle of your code, as it violates the PEP8 style guide.
akubot's answer and some experimentation led me to the answer to this question, so I'm going to accept it.
Do this:
$ exec 3>&1
Then change script.py to be the following:
import sys, os
sys.stderr = open(os.devnull, 'w')
import module
sys.stderr = os.fdopen(3, 'w')
sys.stderr.write('Desired output.\n')
sys.stdout.write('Desired output.\n')
x = int('a')
Then run like this:
$ python script.py 2>/dev/null
yielding the desired output.

How do I execute a function?

I'm new to the python and i was trying to do my first python function, but unfortunately i faced some problems to get the expected result from this simple function please help me to show the output of that function. the below posted function is written in the python editor
i do not know how to call this function from the python shell to show its result.
python code:
def printme( str ):
"This prints a passed string into this function"
print str;
return;
python shell:
>>> printme("d")
>>> Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
printme("d")
NameError: name 'printme' is not defined
$ cd /path/to/your/filename.py
$ python
>>> from filename import printme
>>> printme("hello world!")
You have to load the script as you start the interpreter. From a terminal shell (like bash or zsh):
$ python2 -i script.py
>>> printme("hola")
hola
>>>
On a side note, you don't have to terminate your statements with a semicolon (if they are in their own line), neither have to append a return statement at the end of the function (since indentation and line separation are significative in Python).
If you are using any of the IDEs for python, you could actually run the program in python shell by pressing/typing the Run(F5 equivalent). If that is not the case, read along:
Save the program as test.py (or any other name) in any location of your choice.
Start python shell
>>import sys
>>sys.path
If the directory in which you saved the test.py is present in the output of sys.path, go to step 7
sys.path.append("directory address where you saved the test.py")
>>import test #note .py is removed
>>test.printme("Hello World")
sys.path is the list containing all the directories where python looks for importing modules. By adding (appending) your directory you are ensuring the test.py can be imported as module test. You can then call any functions of test.py as test.fucn()
At step 7 you could have done:
7. >>from test import printme
8. >>printme("Hello again")
If you're using the unix shell:
$ cd C:\yourpath
$ python mypythonfile.py
If you are using the interactive mode, then this:
execfile("C:\\myfolder\\myscript.py")
The long way in interactive mode, but if you prefer to set your default path:
import os
prevPath = os.getcwd() #save the default path
myPath = "C:\myPython\somepath"
os.chdir(myPath) #set your python path
execfile("myscript.py") #executes the file
#os.chdir(prevPath) will restore the default path
Or did i misunderstood your question? If you just want to run a function, it's just as simple as this..
>>> def printme(str):
print str
>>> printme("Hello world!")
Hello world!
>>>
Hope this helps!
My python knowledge is very low... , you question come from this tutorial ,I have all to write as your example on a Linux shell , and i having none problem...
>>> def printme(str):
This print .......................
print str
return
>>> printme('d')
d
how i have Understand , you problem is that you to prove working with idle console and a Linux shell without before your code to save....i think , the examples from shellfly and alKid describe gut , how can you solving your problem...
sorry about my English....

Categories