How to create a python backtrace in form of a string? - python-3.x

To print a backtrace in python on can use the following code:
import traceback
....
traceback.print_stack()
However, I need the backtrace to be used as a string for a logger, something like this:
logger.debug(traceback.print_stack())
which, in this case, does not work. How to most simply get the backtrace to the logger?

The traceback module is full of "format" functions which docuemtnation you can see here https://docs.python.org/3/library/traceback.html
One of which is the format_stack - just pass it a Python frame object, o(by default it uses the current frame) - and it returns you a list of strings, each with the file path and line content of the running position:
logger.debug("\n".join(traceback.format_stack()) )
Or, if you have an exception traceback object, which you can retrieve with a call to sys.last_traceback , you simply pass it's tb_frame attribute to the format_stack function:
logger.debug("\n".join(traceback.format_stack(sys.last_traceback().tb_frame)) )

The simple way of logging the traceback if an exception exists:
logger.debug(traceback.format_exc())
https://docs.python.org/3/library/traceback.html

Related

what is wrong with calling the help function?

I have problems calling the help function on the pd.read_csv()
pandas is already imported as pd
import pandas as pd
help(pd.read_csv())
and I get
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
help(pd.read_csv())
TypeError: parser_f() missing 1 required positional argument: 'filepath_or_buffer'
What is wrong with my help call?
in help(pd.read_csv()) you first called pd.read_csv() (cause of the parenthesis) so the interpreter was expecting an argument for, to execute it and return its result and pass it as argument to help.
The help function accepts functions as arguments so to show help execute help(pd.read_csv).
pd.read_csv is the function, pd.read_csv() is a call to that function.
Quite simply: don't call the object you want help on. Here:
help(pd.read_csv())
The parents after pd.read_csv are the function call operator. You don't want to call this function, you want to pass it as argument to help(), ie:
help(pd.read_csv)

Recreate traceback from file

I have a stacktrace created by the faulthandler after a fatal interpreter crash. Its content looks like below:
File "/path/to/file.py", line <line-number> in <function-name>
File "/path/to/file.py", line <line-number> in <function-name>
I want to create a traceback object from this file, similar to the one from sys.exc_info() to upload it to sentry. Is there any module that will make it easier?
I will not have the scope variables, but it should be possible to capture the code object with content of the files from traceback.
For now the only solution I can think of is to create a class that will behave similar to the traceback object, but this seems like a lot of work (especially if I want the code).
In the end I have prepared my own class that behaves as a traceback object (using duck-typing). The only thing that was important to set valid f_code.co_filename and f_code.co_name and sentry client will extract the source code.

get function call stack from exception

When a python function fails, we get a traceback listing filenames, lines, and function calls.
Is there anyway, within an except block, to pull out only these function names? I would just like a list of the successive calls that lead to the failure.
I have looked at the traceback library and have run dir() on my exception, but I don't see anything.
I took one last look at the traceback documentation and figured it out.
First, use traceback.extract_tb() to get the StackSummary. This is a list of FrameSummary objects, which themselves are tuples whose third value is the function name. In full:
try:
some_function()
except Exception as e:
tb = traceback.extract_tb(e.__traceback__)
for frame in tb:
print(frame[2])
output will be something like
<module>
some_function
another_func_called_by_some_function
...

Python Boto3 OpsWorks KeyError by getting CustomJson

I try to get the custom json from my OpsWorks stacks with python and boto3. Getting the name is ok but if I want to get the CustomJson - KeyError. Don't have a clue why.
import boto3
import traceback
client = boto3.client('opsworks')
response = client.describe_stacks()
max_elements = len(response['Stacks'])
for i in range(max_elements):
stack_Name = response['Stacks'][i]['Name'] # works
try:
stack_CustomJson = response['Stacks'][i]['CustomJson'] # KeyError
except:
traceback.print_exc()
That's the console output:
$ python3 get_custom_json.py
Traceback (most recent call last):
File "get_custom_json.py", line 27, in get_opsworks_details
stack_CustomJson = response['Stacks'][i]['CustomJson']
KeyError: 'CustomJson'
Reading the docs from http://boto3.readthedocs.org/en/latest/reference/services/opsworks.html#OpsWorks.Client.describe_stacks I don't see a difference between 'Name' and 'CustomJson' except that CustomJson is a JSON object. Do I have to transform it?
Thx in advance
You are getting a KeyError occasionally because the CustomStack element in the response is optional. If a custom stack is specified for the stack, it will be returned. Otherwise, the CustomStack key will not be there at all. You should do something like:
if 'CustomStack' in stack:
# do your thing
Had a quick chat with a developer in my company. Got some basic introductions for getting better in coding and python and whatever (must loose some of my admin thinking).
Don't iterate about max_elements, better iterate above 'stack in stacks'.
for stack in response['Stacks']:
print(stack['CustomJson'])
Now it works - I'll get the custom json from the OpsWorks stacks. But still there is the KeyError.
Traceback (most recent call last):
File "get_custom_json.py", line 22, in <module>
get_opsworks_details()
File "get_custom_json.py", line 18, in get_opsworks_details
print(stack['CustomJson'])
KeyError: 'CustomJson'
I'll check if I can fetch him again to see why that's happening.
[EDIT] Blind spot - if a stack has no custom json then the KeyError will occur.

formatting strings for stdin.write() in python 3.x

I'm having a problem where I get errors when I try to execute this code with python 3.2.2
working_file = subprocess.Popen(["/pyRoot/iAmAProgram"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
working_file.stdin.write('message')
I understand that python 3 changed the way it handles strings but I dont understand how to format the 'message'. Does anyone know how I'd change this code to be valid?
many thanks
jon
update: heres the error message i get
Traceback (most recent call last):
File "/pyRoot/goRender.py", line 18, in <module>
working_file.stdin.write('3')
TypeError: 'str' does not support the buffer interface
If you have a string variable that you want to write to a pipe (and not a bytes object), you have two choices:
Encode the string first before you write it to the pipe:
working_file.stdin.write('message'.encode('utf-8'))
Wrap the pipe into a buffered text interface that will do the encoding:
stdin_wrapper = io.TextIOWrapper(working_file.stdin, 'utf-8')
stdin_wrapper.write('message')
(Notice that the I/O is now buffered, so you may need to call stdin_wrapper.flush().)
Is your error message "TypeError: 'str' does not support the buffer interface"? That error message tells you pretty much exactly what is wrong. You don't write string objects to that sdtin. So what do you write? Well, anything supporting the buffer interface. Typically this is bytes objects.
Like:
working_file.stdin.write(b'message')

Resources