How do can I access variable that is declared in a function? - python

I have the following code:
Script1
def encoder(input_file):
# a bunch of other code
# some more code
# path to output of above code
conv_output_file = os.path.join(input_file_gs, output_format)
subprocess.run(a terminal file conversion runs here)
if __name__ == "__main__":
encoder("path/to/file")
And this is how I try to import and how I set it in script2.
Script2
from script1 import encoder
# some more code and imports
# more code
# Here is where I use the output_location variable to set the input_file variable in script 2
input_file = encoder.conv_output_file
What I am trying to do is use variable output_location in another python3 file. So I can tell script2 where to look for the file that it is trying to process without hardcoding it in.
Every time I run the script though I get the following error:
NameError: name 'conv_output_file' is not defined

What I get from your description is that you want to get a local variable from another python file.
Return it or make it a global variable, and import it.
Maybe you have some difficulty in importing it correctly.
Make these two points clear:
you could only import packages in two ways: the package in PYTHONPATH or the local package. Especially, if you want do any relative import, add . before your package name to specify the package you want to import.
Python interpreter treat a directory as a package only if there is a __init__.py under the directory.

what you actually want to do with the variable conv_output_file? if you just want to get the value/object to which conv_output_file binds, then you better use return statement. or if you want to access the variable and do some more thing on that variable i.e modifying it then you can use global to access the variable conv_output_file.
def encoder(input_file):
# a bunch of other code
# some more code
# path to output of above code
global conv_output_file
conv_output_file = os.path.join(input_file_gs, output_format)
you can access the variable now from 2nd script as firstscript.conv_output_file only after calling that function firstscript.encoder(...) because until the function is not invoked variable does not eists . but it is not recommended to use global, you should avoid the use of global.
I think you want to get that value not access variable so better use return statement
def encoder(input_file):
# a bunch of other code
# some more code
# path to output of above code
return conv_output_file
conv_output_file = os.path.join(input_file_gs, output_format)
return conv_output_file
or simply
return os.path.join(input_file_gs, output_format)

I think apart from not returning the variable or not declaring it as a class variable, you're probably making another mistake.
tell that 2nd script
You have to properly import the 1st script into your second script and use the encoder function as an attribute of the 1st script.
For example, name your first script encoder_script.
In second script,
import encoder_script
encoder_script.encode(filename)

Related

'NameError' calling a function in another function

I'm still a beginner in Python. I'm working on a main script in which the function (b) needs to call another function (a) inside it but when I run it I get a 'NameError'. This is what I've done in the main script:
# main script
from __file_a import a
from __file_b import b
par = 'some parameters'
x = b(par)
This is what I've written in the b function
def b(some parameters):
from __file_a import a
out = a(par2)
return out
I've tried to remove the call of a from b and also tried to redefine a in b but when I run the main script I still get an error "NameError: name 'a' is not defined. All the files are in the same folder and all the files are named "__functioname.py".
Can anyone suggest me how to solve this issue?
Many thanks
Not sure if that is just an example name but don't name your files with trailing underscores. Secondly, is there an __init__.py in that folder? You need it for importing from scripts in that folder

Import a variable from a function of python script into another python script

Maybe I'm asking a question that was already answered but even if I searched I couldn't find a solution.
I've a main script called "script.py". The relevant content is:
def file_select():
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename(title="Select a file !!")
print(file_path)
bankFile = pd.read_excel(r'{}'.format(file_path), usecols='{}'.format(column),
skiprows=[i for i in range(int(rowsa))])
bankFile.dropna(inplace=True)
pd.set_option('display.max_columns', None)
pd.set_option('max_rows', None)
....
if __name__ == '__main__':
menu()
conn.close()
The whole script is parsing some columns from a selected excel file and make some arithmetic operations.
I've another script called "db_food.py". It's interacting with sqlite database and with the help of few other functions, does some calculations like calculate spendings for food or save the sum into database etc.
My question is: How can I import and use "bankFile" variable defined in file_select function into "db_food.py" ?
PS: When I use "import script" or "from script import file_select", a file selection dialogbox is shown twice. So I'm asked to select the excel file twice. But I only want to import "bankFile" variable as it is defined in "script.py" and use its content.
That variable is scoped to that function, so as it stands you cannot import it elsewhere. There are also no "tricks" like storing it as a global outside of the scope and importing that, as the value would be whatever you initialized it as (possible None) until the function file_select() is run. Unless you want to considerably restructure the code, perhaps persisting object as a pickled binary in something like Redis is an option. Otherwise, you could consider making this a staticmethod inside class, defining and using the class in script.py and then instantiating an object to use the static method in db_food.py.

Reference a Python file in another Python file

I have two Python files, global.py and test_train.py, both sitting in the same folder. I am trying to allow test_train.py to access everything (functions, variables, etc. in global.py). I cannot get it to work. In the same folder is init.py. I have tried import global and have also referenced Source a Python's file from another Python file, but nothing seems to work. Suggestions?
You should change your file (global.py) name, when you import global.py,
the module name global will conflict with python keyword global
import global # global is keyword in python, you should avoid using this name
# so it will occur error
import global_test # this line is OK, if your .py name is global_test
Typically import global should work.
However, if it doesn't work, you should do a check to see if the import is happening successfully.
A print statement at the end of the global.py script should suffice to tell you so.
Otherwise, if the import is working, then you should try changing your code by encapsulating the entire contents of the global.py in a class, and then creating an object of that class in your test_train.py script to call its functions and attributes.
You can also make use of getattr function to call directly from global.py

How to properly evaluate sage code from within a Python script

I've been trying to evaluate a simple "integrate(x,x)" statement from within Python, by following the Sage instructions for importing Sage into Python. Here's my entire script:
#!/usr/bin/env sage -python
from sage.all import *
def main():
integrate(x,x)
pass
main()
When I try to run it from the command line, I get this error thrown:
NameError: global name 'x' is not defined
I've tried adding var(x) into the script, global x, tried replacing integrate(x,x) with sage.integrate(x,x), but I can't seem to get it to work, I always get an error thrown.
The command I'm using is ./sage -python /Applications/path_to/script.py
I can't seem to understand what I'm doing wrong here.
Edit: I have a feeling it has something to do with the way I've "imported" sage. I have my a folder, let's call it folder 1, and inside of folder 1 is the "sage" folder and the "script.py"
I am thinking this because typing "sage." doesn't bring up any autocomplete options.
The name x is not imported by import sage.all. To define a variable x, you need to issue a var statement, like thus
var('x')
integrate(x,x)
or, better,
x = SR.var('x')
integrate(x,x)
the second example does not automagically inject the name x in the global scope, so that you have to explicitly assign it to a variable.
Here's what Sage does (see the file src/sage/all_cmdline.py):
from sage.all import *
from sage.calculus.predefined import x
If you put these lines in your Python file, then integrate(x,x) will work. (In fact, sage.calculus.predefined just defines x using the var function from sage.symbolic.ring; this just calls SR.var, as suggested in the other answer. But if you want to really imitate Sage's initialization process, these two lines are what you need.)

Pass variable between python scripts

I'm sure this is very simple but I've been unable to get it working correctly. I need to have my main python script call another python script and pass variables from the original script to the script that I've called
So for a simplistic example my first script is,
first.py
x = 5
import second
and my second script is,
second.py
print x
and I would expect it to print x but I get
NameError: name 'x' is not defined
I'm not sure if import is right way to achieve this, but if someone could shed light on it in a simple way that would be great!
thanks,
EDIT
After reading the comments I thought I would expand on my question. Aswin Murugesh answer fixes the import problem I was having, however the solution does not have the desired outcome as I can not seem to pass items in a list this way.
In first.py I have a list which I process as follows
for insert, (list) in enumerate(list, start =1):
'call second.py passing current list item'
I wanted to pass each item in the list to a second python file for further processing (web scraping), I didn't want to do this in first.py as this is meant to be the main 'scan' program which then calls other programs. I hope this now make more sense.
Thanks for the comments thus far.
When you call a script, the calling script can access the namespace of the called script. (In your case, first can access the namespace of second.) However, what you are asking for is the other way around. Your variable is defined in the calling script, and you want the called script to access the caller's namespace.
An answer is already stated in this SO post, in the question itself:
Access namespace of calling module
But I will just explain it here in your context.
To get what you want in your case, start off the called script with the following line:
from __main__ import *
This allows it to access the namespace (all variables and functions) of the caller script.
So now your calling script is, as before:
x=5
import second
and the called script is:
from __main__ import *
print x
This should work fine.
use the following script:
first.py:
x=5
second.py
import first
print first.x
this will print the x value. Always imported script data should be referenced with the script name, like in first.x
To avoid namespace pollution, import the variables you want individually: from __main__ import x, and so on. Otherwise you'll end up with naming conflicts you weren't aware of.
Try use exec
Python3.5:
first.py
x=5
exec(open('second.py').read())
second.py
print(x)
You can also pass x by using:
x=5
myVars = {'x':x}
exec(open('second.py').read(), myVars)
Not sure if this is a good way.
Finally,
I created a package for Python to solve this problem.
Install Guli from PIP.
$ pip install guli
Guli doesn't require installing any additional PIP package.
With the package you can
Guli can be used to pass between different Python scripts, between many processes or at the same script.
pass variables between main Process and another (Multiprocess) Process.
Pass variables between different Python scripts.
Pass variables between 'Main Process' and another (Multiprocess) Process.
Use variables at the same script.
Create / Delete / Edit - GuliVariables.
Example
import guli
import multiprocessing
string = guli.GuliVariable("hello").get()
print(string) # returns empty string ""
def my_function():
''' change the value from another process '''
guli.GuliVariable("hello").setValue(4)
multiprocessing.Process(target=my_function).start()
import time
time.sleep(0.01) # delay after process to catch the update
string = guli.GuliVariable("hello").get()
print(string) # returns "success!!!"
Hope I solved the problem for many people!

Categories

Resources