I defined a convenience function for GDB using the Python API,
import gdb
verbose = True
class HCall(gdb.Function):
def __init__(self, funcname):
super(HCall,self).__init__(funcname)
def log_call(cmd):
if verbose:
print(cmd)
try:
gdb.execute(cmd)
except Exception, e:
print (e)
import traceback
# traceback.print_stack()
traceback.format_exc()
class NewCVar(HCall):
""" allocates a c variable in heap """
def __init__(self):
super(NewCVar,self).__init__("newcvar")
def invoke(self, name, oftype):
cmd = "call gdb.execute(set $" + name + " = malloc(sizeof(" + oftype + "))"
log_call(cmd)
return "$" + name
NewCVar()
I can load this file with "source usefunction.py", and print the help text with "function newcvar". Nevertheless GDB does not know about $newcvar, as I would expect (https://sourceware.org/gdb/onlinedocs/gdb/Functions-In-Python.html).
Does anyone have a clue what can I be doing wrong?
Thanks in advance!
You should probably post exactly what happens, and what you expect to happen.
I tried your program in gdb and gdb does see the function; but since there is a bug in the function, it doesn't actually work. For example I tried:
(gdb) p $newcvar("x", "int")
Traceback (most recent call last):
File "/tmp/q.py", line 23, in invoke
cmd = "call gdb.execute(set $" + name + " = malloc(sizeof(" + oftype + "))"
gdb.error: Argument to arithmetic operation not a number or boolean.
Error occurred in Python convenience function: Argument to arithmetic operation not a number or boolean.
The bug is that ou're trying to gdb.execute a string that looks like call gdb.execute(...). This is weird. call evaluates an expression in the inferior, so using it with an argument containing gdb.execute is incorrect. Instead NewCVar.invoke should make a string like set variable $mumble = ....
Returning a string here is also strange.
I wonder why you want this to be a function rather than a new gdb command.
Related
I run my bash script my_file.sh in a python file as follows:
import subprocess
def rest_api():
params = {
'query': 'indepedence day',
'formats': '["NEWSPAPER"]',
}
subprocess.call(['bash',
'my_file.sh',
f'QUERY={params.get("query")}',
f'DOC_TYPE={params.get("formats")}',
f'LANGUAGE={params.get("lang")}', # returns None!
])
if __name__ == '__main__':
rest_api()
Several of my input arguments in subprocess.call do not normally exist in a dictionary params={} (here I provided f'LANGUAGE={params.get("lang")}' as one example). I handle such unavailability in my_file.sh to initialize with something, for instance:
if [ -z "$LANGUAGE" ]; then LANGUAGE="${LANGUAGE:-[]}"; fi
What I want is to apply some sort of if else statement in subprocess.call function with this logic:
if params.get("lang") is None, do not even send it as an input to bash file, e.g., treat it as I never provided such input for my_file.sh.
Therefore, I tried to rewrote my code like this:
subprocess.call(['bash',
'my_file.sh',
f'QUERY={params.get("query")}',
f'DOC_TYPE={params.get("formats")}',
if params.get("lang"): f'LANGUAGE={params.get("lang")}', # syntax Error
])
which is wrong I get the following invalid syntax error:
Traceback (most recent call last):
File "nationalbiblioteket_logs.py", line 13, in <module>
from url_scraping import *
File "/home/xenial/WS_Farid/DARIAH-FI/url_scraping.py", line 17, in <module>
from utils import *
File "/home/xenial/WS_Farid/DARIAH-FI/utils.py", line 53
if params.get("lang"): f'LANGUAGE={params.get("lang")}',
^
SyntaxError: invalid syntax
Do I have a wrong understanding of applying if else statement for the input arguments of a python function or is there an easier or cleaner way doing it?
Cheers,
You can specify the default when calling .get(), so use an empty string.
f'LANGUAGE={params.get("lang", "")}'
If you don't want the LANGUAGE= argument at all when no value is provided, you need to build the list dynamically.
cmd = ['bash',
'my_file.sh',
f'QUERY={params.get("query")}',
f'DOC_TYPE={params.get("formats")}']
if (lang := params.get("lang")) is not None:
cmd += [f'LANGUAGE={lang}']
subprocess.call(cmd)
Learning python as a beginner. I wanted to copy my code into CMD but it won't work. Here is code
calculation_to_units = 24
name_of_unit = "hours"
def days_to_units(number_of_days):
if number_of_days > 0:
return f"{number_of_days} days are {number_of_days * calculation_to_units} {name_of_unit}"
else:
return "Liczba dni musi być dodatnia :)"
user_input = input("Hello user, enter amount of days you want to calculate to hours\n")
user_input_number = int(user_input)
calculated_value = days_to_units(user_input_number)
print(calculated_value)
despite the fact that it works in Pycharm. I already checked paths. I am not able to solve this problem. When I type in python3 test.py it also says C:\Users\Borys\AppData\Local\Programs\Python\Python310\python.exe: can't open file 'C:\Users\Borys\test.py': [Errno 2] No such file or directory
Also recieved this message "unable to initialize device prn in python"
My internet connection is so bad that it took me 10 minutes to sign up on stack overflow. Additionaly my english knowledge is too small for complex programming explainations.
It can be difficult to paste code that calls input() into a python shell. Both the shell and the input() function read stdin. As soon as python reads the line with input(), it calls input() and that consumes the next line on stdin. In your case, that was a python code line intended to set a variable. That line was consumbed by input and was not read or executed by python. So you got a "variable not defined" error. But you would also have gotten another error because that line was also not the stuff you wanted to input.
Suppose you had the script
val = input("Input value: ")
i_val = int(val)
print(i_val)
And pasted it into the python shell
>>> val = input("Input value: ")
Input value: i_val = int(val)
>>> print(i_val)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'i_val' is not defined. Did you mean: 'eval'?
The line i_val = int(val) was assigned to val - it was not interpreted by the shell. There would be an ">>> " if it did.
With gdb python scripting, I can have a helper function throw an error for an unexpected condition:
def isFOOEnabled( ):
sb = gdb.parse_and_eval( "foo" )
if sb == 0x0:
raise gdb.GdbError( "Fatal error." )
return sb
I can catch the expression not evaluated error in lldb python like so:
def isFOOEnabled( ):
sb = lldb.frame.EvaluateExpression( "foo" )
if sb.GetValue() is None:
return 0
return sb
but I'd also like to force the script to abort like in my gdb version.
For exposition, here is an example of a call to gdb.GdbError:
(gdb) info zregisters
Traceback (most recent call last):
File "/home/pjoot/gdb/zinfo.py", line 157, in invoke
isFOOEnabled( )
File "/home/pjoot/gdb/apis/common.py", line 24, in isFOOEnabled
sb = gdb.parse_and_eval( "sysblk" )
gdb.error: No symbol "sysblk" in current context.
Error occurred in Python command: No symbol "sysblk" in current context.
(gdb)
after which you are back to the (gdb) shell, with a python stacktrace so that you know where things went wrong. Looks like the string parameter that gdb.GdbError takes is actually lost.
Is there a python lldb.* helper function to do that like gdb.GdbError()?
I need to have a couple of functions in Python (either variation) to find and print the name of the file they are stored or called from. For example, consider the following functions are stored in at this address: /my/py/func.py:
def this_file():
# print the address of this file
print('this function is stored at %s' % this_file_address)
and
def that_file():
# print the address of the file that is calling this function
print('this function is called form a file at %s' % that_file_address)
And I have a piece of code stored in /my/py/calls.py:
from func import *
this_file()
that_file()
Now, I want the followings to be printed by the above functions:
/my/py/func.py
/my/py/calls.py
How can I write these functions?
Edit #1
It seems calling that_file() from Jupyter notebooks should be handled differently.
import os
import sys
def this_file():
print(os.path.realpath(__file__))
def that_file():
print(os.getcwd() + "/" + sys.argv[0])
I think this is what you're looking for.
Thanks to #quantik and #Iguananaut (see this), I could find a more general solution that works for calling Python functions from .py and .ipynb files:
func.py
Content:
import os.path
import sys
import urllib.request
import json
def this_file():
# prints the address of this file
print(__file__)
return __file__
def that_file():
# prints the address of the file that is calling this function
if sys.argv[0][-21:]=='ipykernel_launcher.py':
print('Are you calling me from a Jupyter Notebook? Try "that_notebook()" instead.')
return False
else:
print(os.getcwd() + "/" + sys.argv[0])
return os.getcwd() + "/" + sys.argv[0]
def that_notebook(base_url='http://127.0.0.1:8888'):
# prints the address of the notebook that is calling this function
## read more about Jupyter APIL: https://github.com/jupyter/jupyter/wiki/Jupyter-Notebook-Server-API
# See if the url is correct
try:
sessions = json.load(urllib.request.urlopen(base_url+'/api/sessions'))
except:
print('Oops! %s is an invalid URL.' % (base_url+'/api/sessions'))
return False
# See if there is any active session
if len(sessions) == 0:
print('No active session found!')
print('Are you calling me from a Python file? Try "that_file()" instead.')
return False
# In case of multiple active sessions, only print the most recently
latest=max([s['kernel']['last_activity'] for s in sessions])
for s in sessions:
if s['kernel']['last_activity']==latest:
print(s['path'])
return(s['path'])
calls.py
Contents:
from func import *
this_file()
that_file()
that_notebook()
Outputs:
python calls.py
/home/jovyan/work/calls.py
No active session found!
Are you calling me from a Python file? Try "that_file()" instead.
jovyan#c5cd7b908543:~/work$
calls.ipynb
Contents:
from func import *
this_file()
that_file()
that_notebook()
Outputs:
calls.ipynb
/home/jovyan/work/func.py
Are you calling me from a Jupyter Notebook? Try "that_notebook()" instead.
work/calls.ipynb
As part of my current project, I am trying to load the contents of a text file into a list of class objects, then output the objects. On a cursory look my instructor said my code looked fine, but there is no output. I press enter, and...nothing. It's not even printing the "Loaded" code. It just prompts for a new input as if I pressed enter with no instructions. I don't know if the objects are even being properly loaded into the list, and I'm thinking they are not. I am only using the Windows console to run this, so debugging is limited and slow.
I am brand new to Python but this is not a python course, it's algorithms. But it is required that our projects be written in Python, so I'm learning as I go. I usually code in C, C++, or Java. What I've learned, I've taken from here and some helpful tutorials my instructor gave me. I've searched here, but a lot of the code I see looks like what I have. So, I ask you very smart people...
What am I missing here? Did I load the file into memory incorrectly? Is the print line incorrect? Anything else I'm overlooking?
Any help would be most appreciated.
UPDATE: It's running, thanks to the good people below, but now I'm getting the following error:
Traceback (most recent call last): File
"D:\CPSC335\Project_2\project2.py", line 28, in
main() File "D:\CPSC335\Project_2\project2.py", line 24, in main
packages.append(DebianPackage(*line.split())) TypeError: init() missing 2 required positional arguments: 'votes' and 'size'
So, it looks like I'm loading the pulling the data from the text file incorrectly. Is it a problem where the line splits?
CMD Input:
C:\Python34>python D:\CPSC335\Project_2\project2.py D:\CPSC335\Project_2\packages.txt 5
filename: packages.txt
debianutils 128329 90
libgcc1 128327 46
dpkg 128294 2672
perl-base 127369 1969
debconf 121503 168
grep 121426 595
gzip 121346 142
login 121332 980
coreutils 121240 6505
bash 121229 1673
CODE: project2.py
import sys
class DebianPackage:
def __init__(self, name, votes, size):
self.name = name
self.votes = votes
self.size = size
CODE: project2.py (UPDATED based on great help below)
def main():
if len(sys.argv) != 3:
print('error: you must supply exactly three arguments\n\n'+
'usage: python3 <Python source code file> <text file> <n> <W>')
sys.exit(1)
filename = sys.argv[1]
n = int(sys.argv[2])
lines = open(filename).readlines()
print('Loaded "' + filename)
packages = []
for line in lines:
packages.append(DebianPackage(*line.split()))
for package in packages:
print(package.name + ' ' + package.votes + ' ' + package.size)
if __name__ == "__main__":
main()
You define a class and a function named main() in your module but not called it. So call it after definition. Put it at the end:
main()
There is other problems in your code. Your constructor name must be:
def __init__(...)
It's better to use readlines() in place of read():
lines = open(filename).readlines()
And use lines in for loop. So your code will be something like this:
import sys
class DebianPackage:
def __init__(self, name, votes, size):
self.name = name
self.votes = votes
self.size = size
def main():
if len(sys.argv) != 3:
print('error: you must supply exactly two arguments\n\n'+
'usage: python3 <Python source code file> <text file> <n> <W>')
sys.exit(1)
filename = sys.argv[1]
n = int(sys.argv[2])
lines = open(filename).readlines()
print('Loaded "' + filename)
packages = []
for line in lines:
packages.append(DebianPackage(*line.split()))
for package in packages:
print(package.name + ' ' + package.votes + ' ' + package.size)
main()
If you want your script to run, when you execute it by python myapp.py, put or call your main logic by this way:
if __name__ == "__main__":
main()
UPD:
And your class is incorrect, you should use __init__, not _init_:
class DebianPackage:
def __init__(self, name, votes, size):
self.name = name
self.votes = votes
self.size = size