Python - using a string in for in statement? - python

so i know this is a bit of a workaround and theres probably a better way to do this, but heres the deal. Ive simplified the code from where tis gathering this info from and just given solid values.
curSel = nuke.selectedNodes()
knobToChange = "label"
codeIn = "[value in]"
kcPrefix = "x"
kcStart = "['"
kcEnd = "']"
changerString = kcPrefix+kcStart+knobToChange+kcEnd
for x in curSel:
changerString.setValue(codeIn)
But i get the error i figured i would - which is that a string has no attribute "setValue"
its because if i just type x['label'] instead of changerString, it works, but even though changer string says the exact same thing, its being read as a string instead of code.
Any ideas?

It looks like you're looking for something to evaluate the string into a python object based on your current namespace. One way to do that would be to use the globals dictionary:
globals()['x']['label'].setValue(...)
In other words, globals()['x']['label'] is the same thing as x['label'].
Or to spell it out explicitly for your case:
globals()[kcPrefix][knobToChange].setValue(codeIn)
Others might suggest eval:
eval('x["label"]').setValue(...) #insecure and inefficient
but globals is definitely a better idea here.
Finally, usually when you want to do something like this, you're better off using a dictionary or some other sort of data structure in the first place to keep your data more organized

Righto, there's two things you're falling afoul of. Firstly, in your original code where you are trying to do the setValue() call on a string you're right in that it won't work. Ideally use one of the two calls (x.knob('name_of_the_knob') or x['name_of_the_knob'], whichever is consistent with your project/facility/personal style) to get and set the value of the knob object.
From the comments, your code would look like this (my comments added for other people who aren't quite as au fait with Nuke):
# select all the nodes
curSel = nuke.selectedNodes()
# nuke.thisNode() returns the script's context
# i.e. the node from which the script was invoked
knobToChange = nuke.thisNode()['knobname'].getValue()
codeIn = nuke.thisNode()['codeinput'].getValue()
for x in curSel:
x.knob(knobToChange).setValue(codeIn)
Using this sample UI with the values in the two fields as shown and the button firing off the script...
...this code is going to give you an error message of 'Nothing is named "foo"' when you execute it because the .getValue() call is actually returning you the evaluated result of the knob - which is the error message as it tries to execute the TCL [value foo], and finds that there isn't any object named foo.
What you should ideally do is instead invoke .toScript() which returns the raw text.
# select all the nodes
curSel = nuke.selectedNodes()
# nuke.thisNode() returns the script's context
# i.e. the node from which the script was invoked
knobToChange = nuke.thisNode()['knobname'].toScript()
codeIn = nuke.thisNode()['codeinput'].toScript()
for x in curSel:
x.knob(knobToChange).setValue(codeIn)
You can sidestep this problem as you've noted by building up a string, adding in square brackets etc etc as per your original code, but yes, it's a pain, a maintenance nightmare, and starting to go down that route of building objects up from strings (which #mgilson explains how to do in both a globals() or eval() method)
For those who haven't had the joy of working with Nuke, here's a small screencap that may (or may not..) provide more context:

Related

Python: include source file literally [duplicate]

First I do know about 'import'. When I try 'import' it doesn't work. What I'm trying to do is split a single module into two parts, one of which is editable by a group and the other of which is not. I want the group to write well-defined 'retrieval functions' without the temptation or ability to edit the backend code that runs them (even accidentally). The changes in namespace on an 'import' are getting in my way. I'm looking for a macro-style inclusion of File_A's text within File_B, to be run inline as if it were part of File_B.
This is what I'm doing:
I have some generalized code that is designed to call a list of information retrieval functions in turn, and store the info in a unified way. To do this I add its text name to a list:
DataTypes = ['TypeA','TypeB','TypeC']
... and then define a function that knows how to get each type, and returns a populated object class:
def Get_TypeA:
# do some stuff to retrieve info
InfoObj Data
# Populate Data with the info I got
return Data
def Get_TypeB:
# etc. etc.
return Data
def Get_TypeC:
# etc. etc.
return Data
# Backend code below this line, hopefully nobody touches it?
# (But really it would be best if this was in a different file
# that is harder to mess with and has locked-down permissions.)
class InfoObj:
# stuff stuff definitions methods etc.
These functions will be edited by people with only a basic knowledge of Python but often bad coding habits, but who need to be able to frequently customize what is gathered and displayed. I already have a backend that checks the list and calls the functions, but I just want to move those definitions into a separate file from the rest of the backend code, but work as if they were right there inline. (i.e. turn the "hopefully nobody touches it" into a "people have to go out of their way to touch it")
Does Python have this?
When I try using Import, the retrieval functions lose contact with the definition of InfoObj. This happens whether I use 'import otherFile' or 'from otherFile import *'.
EDIT: This is what I'm using to retrieve the various types in a standard way:
THISMODULE = sys.modules[__name__]
for type in DataTypes:
RetrievalFn = getattr( THISMODULE, 'Get_'+type )
Data = RetrievalFn()
StoreInDB(Data)
(though this is boiled down to basics, there are try/except clauses, validation steps to make sure Data was populated correctly and doesn't contain incorrect types or bad stuff, and code to notify the team if and where something breaks but still process the rest of the items. The goal is that someone making edits does not break the rest of the checks, even if their edits broke one of the checks.)
This can be done with execfile(), but you should consider using some other mechanism for this instead such as polymorphism or plugins.

call a variable from a string

I am working on a python hangman game and have my graphics based on a variable, lives, so when you have 1 lives, the corresponding picture appears. i put my graphics into definitions and want to call them from that. Here's my code so far:
if life== 1:
graphics1()
if life==2:
graphics2()
if life==3:
graphics3()
if life==4:
graphics4()
if life==5:
graphics5()
if life==6:
graphics6()
if life==7:
graphics7()
if life==8:
graphics8()
if life==9:
graphics9()
if life==10:
graphics10()
and so on, so is there a command which would allow me to shorten this to one or two lines?
I highly discourage it, but it could be accomplished by doing:
globals()["graphics" + str(life)]()
However there's most definitely a better solution. Presuming that the contents of each graphics*() is similar to one another.
Well, multiple if branches can be expressed via lookup table as
lt = {"1":graphics1(), "2":graphics2()}
and so on.
Accès to if branch via (and provide a fallback function)
lt.get(life, graphics1())
If you want to create the dict dynamically use the dict comprehension and use the getattr to get the function.
Or, as stated above, generalize the function graphics passing the "ith" param to it.

String options for function input python

I am writing a Python function (2.7) where one of the input parameters is a string. The string value should be one of a few values.
i.e. the parameter, in this case "sort" could be any from the list ['first author' 'last author' 'title'] ( the list is actually a bit longer)
Is there a nice way of helping the user supply this input (via tab completion). The ultimate goal is to try and improve the interface for the user so that it is easier for them to use my code and to make less mistakes.
Option 1: Define constants
This might be the best option but there are multiple ways of doing this. My approach is below.
I'm considering creating constants in the module in which the function resides, but this seems messy. My current solution is to include a class with the options, but this makes the input really long, unless I cheat and make the class something nonsensical and short (which is what I've done but it seems wrong and non-obvious). What should I do?
Option 2: Via interpreted documentation
NOTE: I don't think this option actually exists ...
I like the idea of placing code in the documentation which editors could use to perform tab-complete, but I'm not aware of this option existing.
Other options?
Current code (roughly):
class C():
SORT_FIRST_AUTHOR = 'first author'
SORT_LAST_AUTHOR = 'last author'
SORT_TITLE = 'title'
#Ideally these might be selected by: my_module.search.sort_option.FIRST_AUTHOR instead of my_module.C.FIRST_AUTHOR but that's REALLY long
def search(query_string,sort = None): #Changed sort = [], to sort = None per comments
UPDATE: (Trying to clarify the question)
This is somewhat similar to this question, although I think the answers diverge from what I'm looking for because of the specifics of the question.
Pythonic way to have a choice of 2-3 options as an argument to a function
Ideally, I would like the definition of search() to allow tab completion on "sort" by having specifications, something like:
def search(....):
"""
:param sort:
:values sort: 'first author'|'last author'|'title'
"""
But, I'm not aware of that actually being a valid documentation option.
alternatively, I could define some constants that allows this so that the call becomes:
search(my_a,my_b,package_name.C.SORT_FIRST_AUTHOR)
But this seems ugly and wrong.
So when you want the user to pass in one out of a set of options, how do you do it?
Relying on a user to correctly type a string literal is usually a bad idea as it can result in silent errors if the string contains a typo.
It is common to define uppercase variables at the module level, for instance the socket module has
socket.SOCK_STREAM
socket.SOCK_DGRAM
socket.SOCK_RAW
These are passed to functions as parameters, and could easily contain string values.
"Ideally these might be selected by: my_module.search.sort_option.FIRST_AUTHOR instead of my_module.C.FIRST_AUTHOR but that's REALLY long"
Yes that first option seems a bit long. mymodule.SORT_FIRST_AUTHOR seems reasonable though, and using class variables could be appropriate if the constants are constrained to that class and/or if the class is likely to be imported from the module independently.
from mymodule import Searcher
s = Searcher(..., Searcher.SORT_FIRST_AUTHOR)
Prefixing the constants with a common term (like SORT) will aide editors when tab completing entries and makes the constants more descriptive.
You could also consider using a namedtuple
>>> SortOpts = namedtuple('SortOpts', ('FIRST_AUTHOR', 'LAST_AUTHOR'))
>>> SORT_OPT = SortOpts(FIRST_AUTHOR=0, LAST_AUTHOR=1)
>>> SORT_OPT.FIRST_AUTHOR
0
>>> SORT_OPT.FIRST_AUTHOR = 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
This has the advantage of protecting the attributes from being changed, however I don't think this will work with tab completion in most editors.

Is it bad style to reassign long variables as a local abbreviation?

I prefer to use long identifiers to keep my code semantically clear, but in the case of repeated references to the same identifier, I'd like for it to "get out of the way" in the current scope. Take this example in Python:
def define_many_mappings_1(self):
self.define_bidirectional_parameter_mapping("status", "current_status")
self.define_bidirectional_parameter_mapping("id", "unique_id")
self.define_bidirectional_parameter_mapping("location", "coordinates")
#etc...
Let's assume that I really want to stick with this long method name, and that these arguments are always going to be hard-coded.
Implementation 1 feels wrong because most of each line is taken up with a repetition of characters. The lines are also rather long in general, and will exceed 80 characters easily when nested inside of a class definition and/or a try/except block, resulting in ugly line wrapping. Let's try using a for loop:
def define_many_mappings_2(self):
mappings = [("status", "current_status"),
("id", "unique_id"),
("location", "coordinates")]
for mapping in mappings:
self.define_parameter_mapping(*mapping)
I'm going to lump together all similar iterative techniques under the umbrella of Implementation 2, which has the improvement of separating the "unique" arguments from the "repeated" method name. However, I dislike that this has the effect of placing the arguments before the method they're being passed into, which is confusing. I would prefer to retain the "verb followed by direct object" syntax.
I've found myself using the following as a compromise:
def define_many_mappings_3(self):
d = self.define_bidirectional_parameter_mapping
d("status", "current_status")
d("id", "unique_id")
d("location", "coordinates")
In Implementation 3, the long method is aliased by an extremely short "abbreviation" variable. I like this approach because it is immediately recognizable as a set of repeated method calls on first glance while having less redundant characters and much shorter lines. The drawback is the usage of an extremely short and semantically unclear identifier "d".
What is the most readable solution? Is the usage of an "abbreviation variable" acceptable if it is explicitly assigned from an unabbreviated version in the local scope?
itertools to the rescue again! Try using starmap - here's a simple demo:
list(itertools.starmap(min,[(1,2),(2,2),(3,2)]))
prints
[1,2,2]
starmap is a generator, so to actually invoke the methods, you have to consume the generator with a list.
import itertools
def define_many_mappings_4(self):
list(itertools.starmap(
self.define_parameter_mapping,
[
("status", "current_status"),
("id", "unique_id"),
("location", "coordinates"),
] ))
Normally I'm not a fan of using a dummy list construction to invoke a sequence of functions, but this arrangement seems to address most of your concerns.
If define_parameter_mapping returns None, then you can replace list with any, and then all of the function calls will get made, and you won't have to construct that dummy list.
I would go with Implementation 2, but it is a close call.
I think #2 and #3 are equally readable. Imagine if you had 100s of mappings... Either way, I cannot tell what the code at the bottom is doing without scrolling to the top. In #2 you are giving a name to the data; in #3, you are giving a name to the function. It's basically a wash.
Changing the data is also a wash, since either way you just add one line in the same pattern as what is already there.
The difference comes if you want to change what you are doing to the data. For example, say you decide to add a debug message for each mapping you define. With #2, you add a statement to the loop, and it is still easy to read. With #3, you have to create a lambda or something. Nothing wrong with lambdas -- I love Lisp as much as anybody -- but I think I would still find #2 easier to read and modify.
But it is a close call, and your taste might be different.
I think #3 is not bad although I might pick a slightly longer identifier than d, but often this type of thing becomes data driven, so then you would find yourself using a variation of #2 where you are looping over the result of a database query or something from a config file
There's no right answer, so you'll get opinions on all sides here, but I would by far prefer to see #2 in any code I was responsible for maintaining.
#1 is verbose, repetitive, and difficult to change (e.g. say you need to call two methods on each pair or add logging -- then you must change every line). But this is often how code evolves, and it is a fairly familiar and harmless pattern.
#3 suffers the same problem as #1, but is slightly more concise at the cost of requiring what is basically a macro and thus new and slightly unfamiliar terms.
#2 is simple and clear. It lays out your mappings in data form, and then iterates them using basic language constructs. To add new mappings, you only need add a line to the array. You might end up loading your mappings from an external file or URL down the line, and that would be an easy change. To change what is done with them, you only need change the body of your for loop (which itself could be made into a separate function if the need arose).
Your complaint of #2 of "object before verb" doesn't bother me at all. In scanning that function, I would basically first assume the verb does what it's supposed to do and focus on the object, which is now clear and immediately visible and maintainable. Only if there were problems would I look at the verb, and it would be immediately evident what it is doing.

How do you turn an unquoted Python function/lambda into AST? 2.6

This seems like it should be easy, but I can't find the answer anywhere - nor able to derive one myself. How do you turn an unquoted python function/lambda into an AST?
Here is what I'd like to be able to do.
import ast
class Walker(ast.NodeVisitor):
pass
# ...
# note, this doesnt work as ast.parse wants a string
tree = ast.parse(lambda x,y: x+y)
Walker().visit(tree)
In general, you can't. For example, 2 + 2 is an expression -- but if you pass it to any function or method, the argument being passed is just the number 4, no way to recover what expression it was computed from. Function source code can sometimes be recovered (though not for a lambda), but "an unquoted Python expression" gets evaluated so what you get is just the object that's the expression's value.
What problem are you trying to solve? There may be other, viable approaches.
Edit: tx to the OP for clarifying. There's no way to do it for lambda or some other corner cases, but as I mention function source code can sometimes be recovered...:
import ast
import inspect
def f():
return 23
tree = ast.parse(inspect.getsource(f))
print ast.dump(tree)
inspect.getsource raises IOError if it can't get the source code for whatever object you're passing it. I suggest you wrap the parsing and getsource call into an auxiliary function that can accept a string (and just parses it) OR a function (and tries getsource on it, possibly giving better errors in the IOError case).
If you only get access to the function/lambda you only have the compiled python bytecode. The exact Python AST can't be reconstructed from the bytecode because there is information loss in the compilation process. But you can analyze the bytecode and create AST's for that. There is one such analyzer in GeniuSQL. I also have a small proof of concept that analyzes bytecode and creates SQLAlchemy clauseelements from this.
The process I used for analyzing is the following:
Split the code into a list of opcodes with potential arguments.
Find the basic blocks in the code by going through the opcodes and for every jump create a basic block boundary after the jump and before the jump target
Create a control flow graph from the basic blocks.
Go through all the basic blocks with abstract interpretation tracking stack and variable assignments in SSA form.
To create the output expression just get the calculated SSA return value.
I have pasted my proof of concept and example code using it. This is non-clean quickly hacked together code, but you're free to build on it if you like. Leave a note if you decide to make something useful from it.
The Meta library allows you to recover the source in many cases, with some exceptions such as comprehensions and lambdas.
import meta, ast
source = '''
a = 1
b = 2
c = (a ** b)
'''
mod = ast.parse(source, '<nofile>', 'exec')
code = compile(mod, '<nofile>', 'exec')
mod2 = meta.decompile(code)
source2 = meta.dump_python_source(mod2)
assert source == source2
You can't generate AST from compiled bytecode. You need the source code.
Your lambda expression is a function, which has lots of information, but I don't think it still has source code associated with. I'm not sure you can get what you want.

Categories