How can I pass variables from module to module in Python? - python

One of the ways I recently started structuring my programming is by having one main file and multiple different appropriately named files that represent different parts of the project that I am working on.
All different Python Files in one folder.
To then use one file I would simply type:
import filename
This works all well and good, but I noticed that I can't use variables from within another file in that code.
My question is can I import variables, or pass variables from one file to another to make use of them later again?

Each file you import is considered to have its own namespace. You can reference anything in that namespace if you prefix it with the module name.
For example, f you have a file like this:
# filename.py
foobar = 42
You can access foobar with filename.foobar. For example:
import filename
print("foobar is %s" % filename.foobar)

Another way is to use __builtin__ module so that your file main_file.py will contain:
print(thing)
while your whatever.py will contain:
import __builtin__
__builtin__.thing = 1
import main_file
More on that: here

Related

Importing a module from directory with spaces [duplicate]

Do I have to take out all the spaces in the file name to import it, or is there some way of telling import that there are spaces?
You should take the spaces out of the filename. Because the filename is used as the identifier for imported modules (i.e. foo.py will be imported as foo) and Python identifiers can't have spaces, this isn't supported by the import statement.
If you really need to do this for some reason, you can use the __import__ function:
foo_bar = __import__("foo bar")
This will import foo bar.py as foo_bar. This behaves a little bit different than the import statement and you should avoid it.
If you want to do something like from foo_bar import * (but with a space instead of an underscore), you can use execfile (docs here):
execfile("foo bar.py")
though it's better practice to avoid spaces in source file names.
You can also use importlib.import_module function, which is a wrapper around __import__.
foo_bar_mod = importlib.import_module("foo bar")
or
foo_bar_mod = importlib.import_module("path.to.foo bar")
More info: https://docs.python.org/3/library/importlib.html
Just to add to Banks' answer, if you are importing another file that you haven't saved in one of the directories Python checks for importing directories, you need to add the directory to your path with
import sys
sys.path.append("absolute/filepath/of/parent/directory/of/foo/bar")
before calling
foo_bar = __import__("foo bar")
or
foo_bar = importlib.import_module("foo bar")
This is something you don't have to do if you were importing it with import <module>, where Python will check the current directory for the module. If you are importing a module from the same directory, for example, use
import os,sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
foo_bar = __import__('foo_bar')
Hope this saves someone else trying to import their own weirdly named file or a Python file they downloaded manually some time :)

Importing variables from python script into another script is throwing errors that variables are undefined

I am currently writing automation scripts for a proprietary Windows desktop application at work using WinAppDriver with Python. Our application has the user upload a handful of files, does some behind the scenes calculating based on the files uploaded and then spits out results. I have automation in place that uploads these files using the UI and am not having any issues with this specifically. The process to do this is as follows:
Click the ‘Choose File’ button. Browse to file location in pop up window
Click in ‘File Name’ field and input the direct path to the file. Click OK (This is being done with the Python Keyboard library)
Repeat previous steps for all necessary files
Click ‘Go’
To tidy up my scripts, I have set the file paths to variables instead of using their direct paths in my code. Then I just call the variable name for the file I need.
E.g. file_to_upload_1: str = r”C:\Users\user\...\filename.txt
I have created a separate filePaths.py where all these file paths set to variables are stored so adding/modifying them in the future is easy and all in one place.
The issue that I am running into with all of this is when I import this .py that contains my file paths set to variables. Right now, I am doing from filePaths import * for simplicity sake. This is generally frowned upon and VS Code throws warnings at me advising I have imported unused imports. I went ahead and set my variables to separate classes and then tried to import them in the following way: from filePaths import dataset_1 When I do this I get the follow error: Undefined variable “variable_name” and my tests fail to run. It seems like I can only get this all to work if I import everything and I would like to avoid doing that if possible. All my scripts are in the same directory. What am I missing here?
Sample of code:
from filePaths import * <-- THIS WORKS!
# from filePaths import class_1 <-- THIS DOES NOT
#Open App
desired_caps = {}
desired_caps["app"] = "C:\\Users\\Public\\Desktop\\Application_Being_Tested.lnk"
driver = webdriver.Remote("http://127.0.0.1:4723", desired_caps)
#Login
driver.find_element_by_accessibility_id("Username").send_keys("tester")
driver.find_element_by_accessibility_id("UserPassword").send_keys("password")
driver.find_element_by_accessibility_id("btnLogin").click()
###Upload Files###
#First File To Upload
driver.find_element_by_accessibility_id("ChooseFile").click()
time.sleep(.1)
driver.find_element_by_accessibility_id("FileName").click()
keyboard.write(filePaths_variable)
keyboard.press_and_release('enter')
You have three options:
Import everything using the wildcard (i.e. from filePaths import *)
Import select objects (i.e. from filePaths import object1, object2, object3 #...)
Use dot notation (i.e. import filePaths then filePaths.object1 #etc)
Some options may be considered better programming style than others.
The reason the wildcard works is because it is the same as option 2 from above if you had listed all created objects within filePaths on you import statement. In general, you should either selectively import only the methods and objects you need, or just import the script and use dot notation to selectively use methods and objects as needed.
The following example code shows how to use dot notation.
file 1:
# objects_to_import.py
bob = 127
string = 'my string'
def foo():
print('bar')
def bar():
print('foo')
def print_var(var):
print(var)
file 2:
# main.py in the same directory as objects_to_import.py
import objects_to_import
print(objects_to_import.bob)
objects_to_import.print_var(objects_to_import.bob)
objects_to_import.foo()
objects_to_import.bar()
try:
print(string)
except NameError:
print("You didn't import that variable or use correct notation!")
Then, running main.py outputs:
"""
127
127
bar
foo
You didn't import that variable or use correct notation!
"""
The results are identical if main.py instead read:
from objects_to_import import bob, foo, bar, print_var
print(bob)
print_var(bob)
foo()
bar()
try:
print(string)
except NameError:
print("You didn't import that variable or use correct notation!")
Note the if we add the following code to both versions of main.py:
if('bob' in globals()):
print('Bob is in your globals!')
else:
print("Can't find bob in your globals")
We find that bob is in your globals' space when explicitly imported, but is not present when using dot notation with the general non-explicit import statement. There therefore might be pragmatic reasons to choose one import method over the other (e.g. if you program is long and complex and you would like to more easily manage potential name collisions, you should use dot notation).
Alright I've come up with a solution!
I have my filePaths.py module with class_1 in there containing a set of certain variables: var_1, var_2, etc. respectively...
In my script that wants these variables, I'm bringing the module in like so:
import filePaths
path = filePaths.class_1
When I call one of the variables in class_1 instead of just var_1 I call path.var_1 and it comes in with no issues. Thank you everyone for helping out with this!

Get the list of local functions from a python file into another python file

I have a requirement where I need to parse the functions defined in a python file from another python file.
e.g. I have a python file with following contents:
a.py
import os, sys
def function1('text'):
pass
def function2('text'):
pass
Another file is:
b.py
interested_func = 'function2'
function_list = <code to fetch the functions defined in a.py>
if interested_func in function_list:
print 'match found'
How can I get the functions from a.py into b.py so that I can compare the same with the 'interested_func' data and can do specific task based on the match.
Please note that I have 100s of files with different functions defined inside them, so I do not want to import the file.
Please help, thanks in advance!
You should probably use the importlib module:
import importlib
obj = importlib.import_module(module)
print(dir(obj))
You can read more about importlib over in the Python docs.
If that doesn't work for you, then you'll probably want to look at some static code analysis tools such as pylint that might give you a clue into how to do this sort of thing. Another place to look would be to check out PyDev's source code and see how it does code analysis.

Can I import a built-in module twice in both my script and custom module

Is there a downside to importing the same built-in module in both my script and custom module?
I have a script that: imports my custom module and imports the built-in csv module to open a csv file and append any necessary content to a list.
I then have a method in my custom module in which i pass a path, filename and list and writes a csv, but I have to import the csv module again (in my module).
I do not understand what happens when I import the csv module twice so I wanted to know if there is a more uniformed way of doing what I'm doing or if this is ok.
No, there is no downside. Importing a module does two things:
If not yet in memory, load the module, storing the resulting object in sys.modules.
Bind names to either the module object (import modulename) or to attributes of the module object (from modulename import objectname).
Additional imports only execute step 2, as the module is already loaded.
See The import system in the Python reference documentation for the nitty gritty details:
The import statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope.
The short answer is no, there is no downside.
That being said, it may be helpful to understand what imports mean, particularly for anyone new to programming or coming from a different language background.
I imagine your code looks something like this:
# my_module.py
import os
import csv
def bar(path, filename, list):
full_path = os.path.join(path, filename)
with open(full_path, 'w') as f:
csv_writer = csv.writer
csv_writer.writerows(list)
and
# my_script.py
import csv
import my_module
def foo(path):
contents = []
with open(path, 'r') as f:
csv_reader = csv.reader(f)
for row in csv_reader:
contents.append(row)
As a high-level overview, when you do an import in this manner, Python determines whether the module has already been imported. If not, then it searches the Python path to determine where the imported module lives on the file system, then it loads the imported module's code into memory and executes it. The interpreter takes all objects that are created during the execution of the imported module and makes them attributes on a new module object that the interpreter creates. Then the interpreter stores this module object into a dictionary-like structure that maps the module name to the module object. Finally, the interpreter brings the imported module's name into the importing module's scope.
This has some interesting consequences. For example, it means that you could simply use my_module.csv to access the csv module within my_script.py. It also means that importing csv in both is trivial and is probably the clearest thing you can do.
One very interesting consequence is that if any statements that get executed during import have any side effects, those side effects will only happen when the module is first loaded by the interpreter. For example, suppose you had two modules a.py and b.py with the following code:
# a.py
print('hello world')
# b.py
print('goodbye world')
import a
If you run import a followed by import b then you will see
>>> import a
hello world
>>> import b
goodbye world
>>>
However, if you import in the opposite order, you get this:
>>> import b
goodbye world
hello world
>>> import a
>>>
Anyway, I think I've rambled enough and I hope I've adequately answered the question while giving some background. If this is at all interesting, I'd recommend Allison Kaptur's PyCon 2014 talk about import.
You can import the same module in separate files (custom modules) as far as I know. Python keeps track of already imported modules and knows how to resolve a second import.

Importing and using modules in python

New to python and trying to do a random number generator. However, I am having trouble importing the random module. I get a AttributeError when I try to use anything from the random module. Thanks for your help.
#!/usr/bin/python -tt
import random
def main():
x = random.randint(1,1000)
print x
if __name__ == '__main__':
main()
You probably have a file named random.py (or pyc) in your current directory. You can find out where the random module you're using comes from by doing this:
import random
print(random.__file__)
The python importing system vaguely works as follows.
A line like import foo is executed.
Python looks through the directories in sys.path which is a list in the order in which they occur. The first entry in sys.path is the directory in which the main file lives.
When Python finds a file named "foo.py", it executes it and places the global namespace of that file in the module sys.modules['foo'].
Python binds that module to the name foo in the scope in which the original import occurs.
So when you name the file random.py, python finds that file before it searches through the files in the standard library. You are "shadowing" the random module with your file.
This is simplified and doesn't give the full picture. For example, it ignores .pyc files.
Okay, dont name your python program as random.py name it as something else. The interpreter is getting confused by its module and the your program.
I solved the same problem reading this post. I had my file named random.py
Wouldn't it be better to start filename with capital letters so it doesn't match with python module, cos I rookie like me wouldn't be familiar with many python modules.
Thanks

Categories

Resources