So I'm trying to write a python program to integrate into a greater in-house developed python application. This program I'm writing needs to generate an xml document and populate the fields with data stored in variables from another function in a different module.
After realizing I can't have both programs import each other (main program needs to call xmlgen.py to generate the xml doc, while xmlgen.py needs to utilize variables in the main program to generate that doc), I'm a little bit at a loss as to what to do here.
In the example shown below, xmlgen.py needs to use variables from the function sendFax in Faxer.py. Faxer.py needs to call xmlgen.py to generate the document.
snippet from xmlgen.py:
from lxml import etree
from Faxer import coverPage, ourOrg, ourPhonenum, ourFaxnum, emailAddr, sendReceipt, webAddr, comments
from Faxer import sendFax
def generateXml():
#xml file structure
root = etree.Element('schedule_fax')
...
~ A bunch of irrelevant xml stuff
...
grandchild_recipient_name = etree.Element('name')
grandchild_recipient_name.text = cliName
child_recipient.append(grandchild_recipient_name)
Now the piece of the main program I need to utilize the "cliName" variable from...
def sendFax(destOrg, destFax, cliName, casenum, attachments, errEAddr, comment, destName):
creds=requests.auth.HTTPBasicAuth(user,password)
allData=''
allData+='<schedule_fax>\n'
allData+='<cover_page>\n'
allData+='<url>'+prepXMLString(coverPage)+'</url>\n'
allData+='<enabled>true</enabled>\n'
allData+='<subject>'+prepXMLString(cliName)+' - case # '+str(casenum)+'</subject>\n'
Now when I try to import sendFax function from Faxer.py, I'm unable to call any of the variables from the function like,
grandchild_recipient_name.text = sendFax.cliName
does not work. What am i doing wrong here?? I'm not a python guru and am in fact quite new to all of this, so I'm hoping it's something simple. Should I just dump everything into a new function in the main program?
As pointed out above, you are trying to reference cliName as if it is an attribute of the function. This would be closer to being correct if sendFax was a class, but that's another subject. The snippet you have provided is simply a function definition. It doesn't guarantee that this function is ever actually used or give you any idea what cliName actually is, cliName is just the name used by the function internallt to describe the 3rd value supplied as input.
What you need to do is find where sendFax is actually used, rather than where it is defined. Then look at what the variables are called which are passed into it. There are two ways to pass variables into a function: by position and by name. If the variables are being passed by pposition you will find something like:
sendFax(some_name,some_other_name,yet_another_name,...
The third one of these will be the variable which becomes cliName inside the function.
If being passed by name you will see something like
sendFax(cliName=yet_another_name,...
Where once again yet_another_name is the thing which becomes cliName.
Depending on how the programme is structured you may be able to refer to yet_another_name from your program and get the value you need.
from Faxer import yet_another_name
But this will only work if Faxer runs and finishes with the one and only value of yet_another_name assigned. If Faxer iterates through lots of values of yet_another_name, or simply doesn't run sensibly when called as an import you'll need a more sophisticated approach.
Related
I am looking for a way in python to stop certain parts of the code inside a function but only when the output of the function is assigned to a variable. If the the function is run without any assignment then it should run all the inside of it.
Something like this:
def function():
print('a')
return ('a')
function()
A=function()
The first time that I call function() it should display a on the screen, while the second time nothing should print and only store value returned into A.
I have not tried anything since I am kind of new to Python, but I was imagining it would be something like the if __name__=='__main__': way of checking if a script is being used as a module or run directly.
I don't think such a behavior could be achieved in python, because within the scope of the function call, there is no indication what your will do with the returned value.
You will have to give an argument to the function that tells it to skip/stop with a default value to ease the call.
def call_and_skip(skip_instructions=False):
if not skip_instructions:
call_stuff_or_not()
call_everytime()
call_and_skip()
# will not skip inside instruction
a_variable = call_and_skip(skip_instructions=True)
# will skip inside instructions
As already mentionned in comments, what you're asking for is not technically possible - a function has (and cannot have) any knowledge of what the calling code will do with the return value.
For a simple case like your example snippet, the obvious solution is to just remove the print call from within the function and leave it out to the caller, ie:
def fun():
return 'a'
print(fun())
Now I assume your real code is a bit more complex than this so such a simple solution would not work. If that's the case, the solution is to split the original function into many distinct one and let the caller choose which part it wants to call. If you have a complex state (local variables) that need to be shared between the different parts, you can wrap the whole thing into a class, turning the sub functions into methods and storing those variables as instance attributes.
I have a file
outSimulation.py this file has a function called
outlet1 and inside this function there is a variable called data
I want to access this data variable from another program called main.py
I have tried it with absolute imports
from outSimulation import outlet1
values = outlet1.data()
but it doesnt work. Any help is appreciated.
You cannot* access a variable which is local to a function from outside the function.
If you want to access the value of data from a function which is called by outlet1(), you should pass data to that function.
If you want to access the value of data after outlet1() finishes running, you should return data (possibly along with other things) from outlet1().
Alternatively, you can make data a module-level variable. Assuming you assign something to data within outlet1(), you would make it a module-level variable using the global keyword,
def outlet1():
global data
# code
data = ...
# more code
but this tends to be less clean than the other methods.
There are other solutions if outlet1() is defined within a class, but your question suggests that's not the case so I won't get into that.
*Well... uh, never mind. There are some wacky things you can do for debugging, but you're better off not considering those for your purposes.
Functions are not classes, and are specifically designed so that you CAN'T do what you're trying to do. That's the whole basis of functional programming and the concepts behind encapsulation. Even if your function was a class, your code still wouldn't work because you're trying to call the variable as a function (by adding () to data).
Either create data as a global variable that can be referenced inside the function or have the function return a tuple with multiple items, including the original return value and the data variable (messy). You could also rewrite the function in an object-oriented way if that approach suits your problem domain, in which case your code above would make more sense.
I've made a couple of python files with functions like:
def func(a,b,c):
return a+b+c
The functions are often more complicated, but the general idea of them all are the same, receive a couple of predetermined parameters, and return the desired value.
Now, I want to make a separate GUI file for easy use of all the functions. The GUI imports all the different python scripts and via text entry fields I want to be able to give the desired parameters for each function. The problem is that the functions vary greatly in what kinds of parameters they expect, so I wanted to make each function able to return a help string to the GUI with a short explanation of what the function needs to run. In the GUI file I'm using getattr to save the desired function:
methodtocall = getattr(Nuclear, func)
I can then call the function with parameters gained for textfields, like:
methodtocall(textfield1.get(),textfield2.get())
The problem, as I said above, is that for the GUI to be useful, I need a help sentence to be printed to the GUI the moment I select a function. I tried to make an adjustment in the functions themselves, example:
def func(a,b,c):
help = "give a as string, b as list, c as integer"
if no_parameters:
return help
else:
return desired_value
The problem is that the methodtocall function gives a TypeError, since I try to launch it without any parameters: methodtocall()
The solution would be something that called the desired function the moment I select it in the GUI, and retrieves the help line for the desired function and displays it in a help textfield in the GUI, does anyone have any ideas?
Place the help text in the first unassigned string in the function definition, like this:
def func(a,b,c):
"""
This function adds three numbers.
"""
return a+b+c
Now, this text is available through the variable __doc__:
print(func.__doc__)
#
# This function adds three numbers.
#
You do not even need to call the function.
I'm not an expert at python, so bear with me while I try to understand the nuances of variable scopes.
As a simple example that describes the problem I'm facing, say I have the following three files.
The first file is outside_code.py. Due to certain restrictions I cannot modify this file. It must be taken as is. It contains some code that runs an eval at some point (yes, I know that eval is the spawn of satan but that's a discussion for a later day). For example, let's say that it contains the following lines of code:
def eval_string(x):
return eval(x)
The second file is a set of user defined functions. Let's call it functions.py. It contains some unknown number of function definitions, for example, let's say that functions.py contains one function, defined below:
def foo(x):
print("Your number is {}!".format(x))
Now I write a third file, let's call it main.py. Which contains the following code:
import outside_code
from functions import *
outside_code.eval_string("foo(4)")
I import all of the function definitions from functions.py with a *, so they should be accessible by main.py without needing to do something like functions.foo(). I also import outside_code.py so I can access its core functionality, the code that contains an eval. Finally I call the function in outside_code.py, passing a string that is related to a function defined in functions.py.
In the simplified example, I want the code to print out "Your number is 4!". However, I get an error stating that 'foo' is not defined. This obviously means that the code in outside_code.py cannot access the same foo function that exists in main.py. So somehow I need to make foo accessible to it. Could anyone tell me exactly what the scope of foo currently is, and how I could extend it to cover the space that I actually want to use it in? What is the best way to solve my problem?
You'd have to add those names to the scope of outside_code. If outside_code is a regular Python module, you can do so directly:
import outside_code
import functions
for name in getattr(functions, '__all__', (n for n in vars(functions) if not n[0] == '_')):
setattr(outside_code, name, getattr(functions, name))
This takes all names functions exports (which you'd import with from functions import *) and adds a reference to the corresponding object to outside_code so that eval() inside outside_code.eval_string() can find them.
You could use the ast.parse() function to produce a parse tree from the expression before passing it to eval_function() and then extract all global names from the expression and only add those names to outside_code to limit the damage, so to speak, but you'd still be clobbering the other module namespace to make this work.
Mind you, this is almost as evil as using eval() in the first place, but it's your only choice if you can't tell eval() in that other module to take a namespace parameter. That's because by default, eval() uses the global namespace of the module it is run in as the namespace.
If, however, your eval_string() function actually accepts more parameters, look for a namespace or globals option. If that exists, the function probably looks more like this:
def eval_string(x, namespace=None):
return eval(x, globals=namespace)
after which you could just do:
outside_code.eval_string('foo(4)', vars(functions))
where vars(functions) gives you the namespace of the functions module.
foo has been imported into main.py; its scope is restricted to that file (and to the file where it was originally defined, of course). It does not exist within outside_code.py.
The real eval function accepts locals and globals dicts to allow you to add elements to the namespace of the evaluted code. But you can't do anything if your eval_string doesn't already pass those on.
The relevant documentation: https://docs.python.org/3.5/library/functions.html#eval
eval takes an optional dictionary mapping global names to values
eval('foo(4)', {'foo': foo})
Will do what you need. It is mapping the string 'foo' to the function object foo.
EDIT
Rereading your question, it looks like this won't work for you. My only other thought is to try
eval_str('eval("foo(4)", {"foo": lambda x: print("Your number is {}!".format(x))})')
But that's a very hackish solution and doesn't scale well to functions that don't fit in lambdas.
I am attempting to use a module called interface.py which defines a list of conditions and a few functions to check arguments against those conditions. There are many thousands of conditions however, and so I want to use a dictionary instead of a list to prevent needing to look at all of them. To do this I'm using the following code:
def listToDictionary(list):
"""This function takes a list of conditions and converts it to a dictionary
that uses the name of the condition as a key."""
d = {}
for condition in list:
if condition.name.lower() not in d:
d[condition.name.lower()] = []
d[condition.name.lower()].append(condition)
return d
conditionList = listToDictionary(conditions.list) #the condition list comes from another module
Further into the file are the actual interface functions that take arguments to compare with the list of conditions - these functions are written assuming that conditionList will be a dictionary.
Unfortunately this isn't working. Giving error details is difficult because this code is being imported by a django page and I am trying to avoid talking about django so this question stays uncomplicated. Essentially the pages including this code will not load, and if I change it back to just using a list everything works fine.
My suspicion is that the problem has to do with how Python treats import statements. I need the listToDictionary conversion to run as soon as interface.py is imported, otherwise the interface functions will expect a dictionary and get a list instead. Is there any way to ensure that this is happening?
An educated guess: the list in conditions.list is not yet fully constructed when your module is being imported. As a result, you get a dictionary that is missing some entries or even empty, which is causing problems later. Try deferring the construction of the dict, like this:
conditionTable = None # shouldn't call it list if it's a dict
def get_cond_table():
global conditionTable
if conditionTable is None:
conditionTable = listToDictionary(conditions.list)
return conditionTable
Instead of referring to conditionList in your functions, refer to get_cond_table().
Alright, I found out that the problem was in another function that was still expecting the dictionary to be a list. The reason I couldn't see it right away is that Django left a very cryptic error message. I was able to get a better one using python manage.py shell and importing the module manually.
Thanks for your help everyone.