Python Is it possible to recreate a whole call stack? - python

I'm interested in experimenting with python. I know I can inspect and inject local and global variables into a frame using frame.f_locals and frame.f_globals, but I am now itching to create a full call stack.
What is keeping me from just changing the stack information is the fact that python doesn't allow me to change it.
I have actually considered programmatically transforming the python module I am using, in order to simulate winding the stack. But I am aware it is a terrible solution because client code usage of if, while, with and try would easily break my code.
I've also looked at manipulating frame.f_back, to no avail. It's read-only.
>>> import sys
...
... frm = sys._getframe()
...
... frm.f_back = None
Traceback (most recent call last):
File "<pyshell#4>", line 5, in <module>
frm.f_back = None
TypeError: readonly attribute
What I'm trying to do
As an experiment, I'm trying to implement fork() across a network.
I'm aware stackless python may have what I want, but it's still impossible to change the frame.f_back attribute.

Have a look on Online Python Tutor (http://www.pythontutor.com/). What it does is that it captures frames during execution to create visualization of python code. So, you could use the captured frames.

>>> type(sys._getframe())()
TypeError: cannot create 'frame' instances
Sorry.

You should look at the AST module and the symtable module

Related

Save and load variables using shelve

I'm trying to implement a code that will generate a lot of scenarios. This scenarios will be executed after by a 3 different simulators.
I'm saving my scenarios in a file using shelve. My code is like this:
def save_variables(I, T, R, C, lambd, K, iteraction):
filename='/folder/shelve_{}.out'.format(iteraction)
my_shelf = shelve.open(filename,'n')
for key in dir():
try:
my_shelf[key] = locals()[key]
except TypeError:
pass
my_shelf.close()
and I'm loading data in each simulators like this:
my_shelf = shelve.open(filename)
my_shelf = shelve.open(filename)
for key in my_shelf:
globals()[key]=my_shelf[key]
my_shelf.close()
This part works great. My problem is:
If I run all the code together, in the same terminal of execution, for example, first the scenario_generator, after the simulator_1, after simulator_2 and at least simulator_3, in the same line of execution, the codes works great.
But if I run only the scenario_generator in one terminal and start each simulation in other 3 differents terminals of execution, I receive the follow error:
Number of arguments: 2 arguments.
Argument List: on
Iteraction 0
Traceback (most recent call last):
File "main.py", line 53, in <module>
onets.onets(i)
File "/Users/simulator_1.py", line 31, in simulator_1
n = [[0 for x in range(I+1)] for y in range(T+1)]
NameError: name 'T' is not defined
I understand with this notification that was not possible to read the data saved by shelved. But the files was in folder. Someone knows how I can fix this problem?
P.S.: Is important to me execute in this way (separately) because I should start the 3 simulator as the same time, in different terminals of execution. This will provide a big economy of execution time to have my results.
thanks everyone.
Without being sure, I suspect you are not storing all the variables you think you are in the shelve.
When the steps are together in a single script, if some values are not written in the shelve, you won't notice because you explicitely silent the TypeError` exception.
This is not recommended as errors go unnoticed. You probably made it exactly to avoid some error that was happening.
Because the scripts are together in the same file they share the same global scope.
When you read the values back into the global scope, and some values are missing, you are probably covered by the original values in that same global scope.
So you miss some values, but when you need them they were already there in global scope to be read from.
With separate files there is no more a common global scope. Any missing value will cause an error.
Remove the pass and make the except clause print the current key and value to check for missing keys.
Other than that I see no problem in generating file data to read later from whatever different processes/scripts like you described (given there are no cache/sync trouble and you open the files for reading only)

Is there a version of __file__ that when used in a function, will get the name of the file that uses the library?

So, as a joke I wrote a version of goto for python that I wanted to use as a library. The function I wrote for it is as follows.
def goto(loc):
exec(open(__file__).read().split("# "+str(loc))[1],globals())
quit()
This works for cases where it is in the file where goto is used, such as this:
def goto(loc):
exec(open(__file__).read().split("# "+str(loc))[1],globals())
quit()
# hi
print("test")
goto("hi")
However, if I import goto in another file, it doesn't work as
__file__
will always return the file with the function in it, not the one it is used in. Is there an equivalent of file that will allow me to import a file with the goto function in it and have it work?
Yes, you can if you inspect the call stack:
import inspect
def goto():
try:
frame = inspect.currentframe()
print(frame.f_back.f_globals['__file__'])
finally:
# break reference cycles
# https://docs.python.org/3.6/library/inspect.html#the-interpreter-stack
del frame
goto()
Note that the call stack is actually python implementation dependent -- So for some python interpreters, this might not actually work...
Of course, I've also shown you how to get the caller's globals (locals can be found via frame.f_back.f_locals for all of your execing needs).
Also note that it looks like you can implement a jump command by writing to the frame's f_lineno -- which might be a better way to implement your goto. I've never done this though so I can't really advise you on how to actually code it up :-)

Python os.mknod in windows

I was trying to use the os.mknod function in Python 3.5.0 in Windows 7, however I find the error:
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
os.mknod
AttributeError: module 'os' has no attribute 'mknod'
I guess it's supposed to be there, since https://docs.python.org/3/library/os.html doesn't say anything about limited availability. Is there another option to use for a similar function in Windows? I'm just looking to create an empty file in a specific path, and I was thinking calling open(path, 'w') is kinda ugly for this.
I don't know if this might be a version specific problem since I've never used Python in Windows before.
Since commit in 2016, this is now documented:
Availability: Unix.
I'm new here and on Python World (although learning kind of quickly...), and just stumbled uppon the same issue.
My suggestion: for now, I would just go with the following and turn a blind eye on it...
with open('name_your_file.extention', 'w') as an_alias_for_it:
pass
In the end, it's not neat, but will be naturally "portable" among POSIX and NT systems.

PyWin32 get network information/statistics

I am trying to get Network Statistics for my Windows 7 system using PyWin32.
The steps I followed:
1) Run COM MakePy utility and than select network list manager 1.0
type library under type library.
2) Above process generated this python file.
Now the problem I am facing is after the above two steps what should be my next step. I tried a couple of things like:
I copied the CLSID = IID('{DCB00000-570F-4A9B-8D69-199FDBA5723B}') line from the above generated python file and used it like
>>> import win32com
>>> obj = win32com.client.gencache.GetClassForCLSID("{DCB00000-570F-4A9B-8D69-199FDBA5723B}")
>>> obj.GetConnectivity()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: unbound method GetConnectivity() must be called with INetworkListManager instance as first argument (got nothing instead)
When I do obj.method() it show a list of all available method.
So, now I have no idea what to do or how to proceed and what is the general process of using Type library with pywin32.
The above task is just a part of learning process on how to use PyWin32,COM MakePy utility.
Is this even achievable using pywin32.?
You'll need to use win32com.client.Dispatch to actually create the object.
Also, the class you start with is the CoClass, in this case
class NetworkListManager(CoClassBaseClass): # A CoClass
is the one you want.
win32com.client.Dispatch('{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')
works here.
Many of these Dispatch classes have a human readable dotted name as an alias, although
this particular one doesn't seem to.

High resolution time in python on a linux system

This is a 2-part question and the first part is simple. I'm trying to get the current time as a high resolution number, something easily done with the Time::HiRes module in perl. I did find answers this questions elsewhere to use using time.time() in python. The only thing is when I do this all I get as 2 significant digits and am wondering if I need to import something else or set something in my environment or what. Look at this:
>>> import time
>>> print time.time()
1326459121.68
My second question has to do with setitimer, which according to the docs says it will deliver alarms and the time can be specified as a floating point number. Sounds exactly what I want. In fact, according to this - python timer mystery it looks pretty easy to use. But when I make an exact copy of that example, I get this:
[root#poker python]# ./signal.py
Traceback (most recent call last):
File "./signal.py", line 10, in ?
signal.setitimer(signal.ITIMER_REAL, 2, 2)
AttributeError: 'module' object has no attribute 'setitimer'
Perhaps part my the problem is that as a new python user I'm still not 'one with python' and perhaps am not understanding what the error message it trying to tell me. Is it complaining that it can't find signal.setitimer OR is there something wrong with the attributes I'm passing? I was wondering if it couldn't resolve signal.ITIMER_REAL and so tried calling it with a 0 just to see what would happen and now it's telling me:
[root#poker python]# ./signal.py
Traceback (most recent call last):
File "./signal.py", line 10, in ?
signal.setitimer(0, 2, 2)
AttributeError: 'module' object has no attribute 'setitimer'
so I have to believe it is signal.setitmer itself that is having issues.
Aha! I just figured out the problem by trying this on a VM with a newer version of python and it works just fine. Looks like setitimer is not available with my version of python but how can I tell from the error message? Shouldn't it be saying the module has no method? Calling the missing method an attribute is pretty confusing.
Maybe that's just part of the learning curve. Anyhow I thought I'd keep this second question in here so other might benefit, but I still am still stumped by what I can't get high resultion time from time.time() which still only reports in hundredths of a second even on this newer version of python.
time.time() returns more digits but the repr truncates to 2.
>>> import time
>>> time.time()
1326460396.626451
>>> print time.time()
1326460422.68
The problem with not being able to find setitimer is quite simply because you've named your python script 'signal.py', when you 'import signal' in your script, you're actually importing your script -- not the signal module. Just rename it to something else and it'll work.

Categories

Resources