Python: Apply if statement from string - python

I have an if statement in a .ini file:
critical= $TREND$>=40
In my script I replace $TREND$ by my value so I have in a variable:
critical = "10.5>=40"
I try to execute this if statement to know if it's True or False.
if critical:
print "It's critical!"
(I know it will just check if critical is empty)

One option is to use eval:
critical = eval("10.5>=40")
However, you must be sure that what is "eval'ed" is completely trusted, because it allows you to execute any arbitrary python code. That is, don't use this if any part of the string is passed in by an "untrusted entity" (user, external api, etc).
Another, possibly better, option might be to use a "template parser" which allows "untrusted" or "sandboxed" execution. For example, the Jinja Sandbox mode.

I would urge you to change your .ini to have following:
critical_low
critical_high
this way you avoid two problems - you don't have to use eval which can be very dangerous, and you don't have logic in your .ini unless you do want logic there which still can be solved without using eval
said that eval will work fine if it's just a hacky script

Related

What is the recommended way to update a proc entry from Python

I have a linux proc entry in /proc/sys/fs/offs/ts/enable which toggles a flag in a custom kernel module. Setting the value to 1 will enable a mode in the module, setting to 0 will disable that mode.
In bash, to enable the mode, I would simply do
echo 1 > /proc/sys/fs/offs/ts/enable
And to disable it,
echo 0 > /proc/sys/fs/offs/ts/enable
I have a daemon written in Python 2.7 which will look for some external event trigger, and when that event fires, should enable or disable the feature in the kernel module. The daemon is run with root privileges, so I shouldn't run into any kind of permissions issues.
Is there a recommended way of setting this value from python?
For example, say my function right now looks like this.
def set_mode(enable=True):
with open('/proc/sys/fs/offs/ts/enable', 'w') as p:
if enable:
p.write("1")
else:
p.write("0")
p.flush()
There are a couple of problems with your code.
Firstly, you want to write to the file, but you're opening it in read mode.
Secondly, .write expects string data, not an integer.
We can get rid of the if test by exploiting the fact that False and True have integer values of 0 & 1, respectively. The code below uses the print function rather than .write because print can convert the integer returned by int(enable) to a string. Also, print appends a newline (unless you tell it not to via the end argument), so this way the Python code performs the same action as your Bash command lines.
def set_mode(enable=True):
with open('/proc/sys/fs/offs/ts/enable', 'w') as p:
print(int(enable), file=p)
If you want to do it with .write, change the print line to:
p.write(str(int(enable)) + '\n')
There's a way to do that conversion from boolean to string in one step: use the boolean to index into a string literal:
'01'[enable]
It's short & fast, but some would argue that it's a little cryptic to use booleans as indices.
Linux exposes the /proc filesystem, as the name says, as files. That means you'll operate on those files like you would do with any other file. Your suggested function is basically perfect regarding how to access /proc, but PM 2Ring's recommendations are definitely valid.
Since it is a low level code, not intended to be portable, I would use os module. It has functions open, write and close that are almost direct wrappers of the C counterparts.
More like C equals less surprises!

How can I set breakpoints by regular expression in GDB via Python

I would like to script some behaviour in GDB using Python: given a regular expression describing a set of functions, instantiate a subclass of gdb.Breakpoint (eg. MyBreakpoint) for each function matched.
There is no equivalent of rbreak in GDB's Python module. I had thought of doing this:
gdb.execute('rbreak {:s}'.format(regexp))
breakpoints = gdb.breakpoints()
# Extract breakpoint strings, delete existing breakpoints, and
# recreate them using my subclass.
for bp in breakpoints:
loc = bp.location
bp.delete()
MyBreakpoint(loc)
...however this suffers from the problem that there might already be some user defined breakpoints, and this would destroy them.
My next idea was to iterate over all possible functions to break on, and do the matching using Python's re module. However, there doesn't seem to be any way to list functions available for breaking from within Python.
My question is: could either of these approaches be salvaged so that they will work reliably and not clobber state set by a user in an interactive session; or is there some other way to achieve this? Or will I have to compromise on "not clobbering user state?"
Since rbreak creates new breakpoint objects, even if the breakpoints are for the same locations as pre-existing breakpoints, you can run gdb.breakpoints() before and after the execution of rbreak to see which breakpoints were added.
obreakpoints = gdb.breakpoints();
gdb.execute('rbreak {:s}'.format(regexp))
breakpoints = set(gdb.breakpoints()).difference(set(obreakpoints))

Python REPL: issuing commands in advance to execute after block

This is a bit of an odd question; it came up in the context of a tool that exposes a Python API, which we spend a lot of time querying interactively from the REPL. The particular idiom causing issues is something like this:
for var in slow_generator_of_giant_list():
stats = update(stats, var)
print stats
To enter this at the REPL, I can type this:
>>> for var in slow_generator_of_giant_list():
... stats = update(stats, var)
...
If I now attempt to type the print, I get a syntax error due to improper indentation. (Or else I put the print inside the loop and do it on every iteration.)
But if I hit enter to go to the next line, the loop runs immediately, and I have to wait for it to finish, or type the print command in the face of possible output coming at me, etc.
Obviously I can define a function containing the above, and it might be worth saving into a file anyway, but in the general case we're constructing these on the fly, and it would be nice to have a way to "schedule" a command to run after the end of a loop from the REPL. In a language with block delimiters, I could of course put it after the ending delimiter (and any necessary statement separator). But my coworkers and I were stumped trying to do something similar here.
Is there perhaps an ugly abuse of Pythonic syntax that will do the trick that my coworkers and I couldn't think of? Or a recommended way to avoid the problem while still making it easy to throw together ad hoc interactive queries?
Thanks for any pointers.
Not beautiful, but this should work:
>>> mygen = slow_generator_of_giant_list()
>>> try:
... while True: stats = update(stats, mygen.next())
... except StopIteration:
... print stats
...
I would just say that you would find it easier just to not use the interactive shell for this.
It's not much effort to save a file and run it. You only have to keep it around for as long as you use it.
I actually have found this answering on SO. I keep a file open in my text editor with a terminal in the right directory, and just use it as a scratchpad for mocking up answers in.

Given the my code is open source and I'm running on a server, and I accept nearly-raw code, what's the worst that can happen to me?

I'm looking at several cases where it would be far, far, far easier to accept nearly-raw code. So,
What's the worst you can do with an expression if you can't lambda, and how?
What's the worst you can do with executed code if you can't use import and how?
(can't use X == string is scanned for X)
Also, B is unecessary if someone can think of such an expr that given d = {key:value,...}:
expr.format(key) == d[key]
Without changing the way the format looks.
The worst you can do with an expression is on the order of
__import__('os').system('rm -rf /')
if the server process is running as root. Otherwise, you can fill up memory and crash the process with
2**2**1024
or bring the server to a grinding halt by executing a shell fork bomb:
__import__('os').system(':(){ :|:& };:')
or execute a temporary (but destructive enough) fork bomb in Python itself:
[__import__('os').fork() for i in xrange(2**64) for x in range(i)]
Scanning for __import__ won't help, since there's an infinite number of ways to get to it, including
eval(''.join(['__', 'im', 'po', 'rt', '__']))
getattr(__builtins__, '__imp' + 'ort__')
getattr(globals()['__built' 'ins__'], '__imp' + 'ort__')
Note that the eval and exec functions can also be used to create any of the above in an indirect way. If you want safe expression evaluation on a server, use ast.literal_eval.
Arbitrary Python code?
Opening, reading, writing, creating files on the partition. Including filling up all the disk space.
Infinite loops that put load on the CPU.
Allocating all the memory.
Doing things that are in pure Python modules without importing them by copy/pasting their code into the expression (messing with built in Python internals and probably finding a way to access files, execute them or import modules).
...
No amount of whitelisting or blacklisting is going to keep people from getting to dangerous parts of Python. You mention running in a sandbox where "open" is not defined, for example. But I can do this to get it:
real_open = getattr(os, "open")
and if you say I won't have os, then I can do:
real_open = getattr(sys.modules['os'], "open")
or
real_open = random.__builtins__['open']
etc, etc, etc. Everything is connected, and the real power is in there somewhere. Bad guys will find it.

Printing Variable names and contents as debugging tool; looking for emacs/Python shortcut

I find myself adding debugging "print" statements quite often -- stuff like this:
print("a_variable_name: %s" % a_variable_name)
How do you all do that? Am I being neurotic in trying to find a way to optimize this? I may be working on a function and put in a half-dozen or so of those lines, figure out why it's not working, and then cut them out again.
Have you developed an efficient way of doing that?
I'm coding Python in Emacs.
Sometimes a debugger is great, but sometimes using print statements is quicker, and easier to setup and use repeatedly.
This may only be suitable for debugging with CPython (since not all Pythons implement inspect.currentframe and inspect.getouterframes), but I find this useful for cutting down on typing:
In utils_debug.py:
import inspect
def pv(name):
record=inspect.getouterframes(inspect.currentframe())[1]
frame=record[0]
val=eval(name,frame.f_globals,frame.f_locals)
print('{0}: {1}'.format(name, val))
Then in your script.py:
from utils_debug import pv
With this setup, you can replace
print("a_variable_name: %s' % a_variable_name)
with
pv('a_variable_name')
Note that the argument to pv should be the string (variable name, or expression), not the value itself.
To remove these lines using Emacs, you could
C-x ( # start keyboard macro
C-s pv('
C-a
C-k # change this to M-; if you just want to comment out the pv call
C-x ) # end keyboard macro
Then you can call the macro once with C-x e
or a thousand times with C-u 1000 C-x e
Of course, you have to be careful that you do indeed want to remove all lines containing pv(' .
Don't do that. Use a decent debugger instead. The easiest way to do that is to use IPython and either to wait for an exception (the debugger will set off automatically), or to provoke one by running an illegal statement (e.g. 1/0) at the part of the code that you wish to inspect.
I came up with this:
Python string interpolation implementation
I'm just testing it and its proving handy for me while debugging.

Categories

Resources