List not defined when importing a function - python

I made two modules in Python. The other one is a sentinel-controlled loop that asks for the data and the other module contains the functions needed for computation. When I import Module 2 (module with functions), I get a Name Error.
NameError: name 'x' is not defined
where x is the argument of my function
convert(x)
but x is a defined list in Module 1 (sentinel-controlled loop) where I store data. I can't figure out why the imported module does not consider it.
I imported the other module as
import ModuleName
What could be the problem?
Disclaimer: I'm a beginner in Python so I'm not really very familiar with it.

It has to do with the way you import. There are a couple of ways to resolve this.
In the example below, you import module_name and then call function x in the proper namespace.
import module_name
module_name.x()
Another way would be to explicitly import function x from module_name.
from module_name import x
x()
I highly advise you to do some reading on how importing works in python, w3schools is always a good starting point.

Related

How does dot operator relate to Namespaces?

As i was going through python basics and introduction one thing that really confuses me is namespaces. I cant seem to understand how they work.
For instance in Cs50 course they brush over the concept but i wanted to get clearer understanding of it if possible because it seems very important to grasp. For example this code:
import cs50
x = get_int("x: ")
y = get_int("y: ")
print(x + y)
Causes this error:
python calculator.py
Traceback (most recent call last):
File "/workspaces/20377622/calculator.py", line 3, in
x = get_int("x: ")
NameError: name 'get_int' is not defined
What is wonder is why when cs50.get_int() is written instead interpreter doesn't throw an error? Is it because cs50 library is seen as its own namespace structure and . goes into that structure to get_int location? What does . operator do exactly here in terms of namespaces ?
You import cs50, so you have a name "cs50", you can use
cs50.get_int()
but namespaces has no name get_int.
You can use from cs50 import get_int to import name "get_int"
To answer this question, let's talk about modules.
In Python, "module" is used to refer to two things. First, a piece of code, usually a .py file. Second, the object that is created for the namespace of that code when it is run.
When you do import foo, a couple of things happen.
Python checks if foo has already been imported. If so, it skips to the last step.
Python looks up where it can find foo, for example if there is a foo.py in the right place.
Python creates a fresh namespace object and stores a reference to it in sys.modules['foo']
Python runs the code that it found, using that namespace object as its "global" namespace.
Python goes back to the importing module, and adds a global variable foo in the namespace of importing module that points to sys.modules['foo'].
You can then access any global variable bar that was created in the foo.py module by using foo.bar.
You could also use from cs50 import get_int which works like this:
import cs50
get_int = cs50.get_int
... except that the name cs50 is not assigned to.
If you're asking why it works that way: this way different modules can define the same name for classes, functions or constants, and they won't conflict with each other.
Now, if you know you're only using get_int from cs50, and you don't have any other get_int either in your main module or that you imported, the from ... import syntax is very useful to not have to write cs50.get_int every time you want to use it.

How to use from x import y using importlib in Python

I wanted to install and import a package from script. Then I wanted to add from x import y and from x import * in that script.(I was making some functions actually).
I successfully installed and imported using subprocess and importlib. But I'm at a loss in from x import y and from x import *. Tried these codes and some others.
globals()[package] = importlib.import_module('package','class')
globals()[package] = importlib.import_module('class','package')
globals()[package] = importlib.import_module('package','*')
globals()[package] = importlib.import_module('*','package')
importlib.import_module('gtts','gTTS')
importlib.import_module('gtts','*')
But they didn't work. Shows:
NameError: name 'gTTS' is not defined
ModuleNotFoundError: No module named 'gTTS'
etc.
I don't think you can load methods directly, since this method just loads modules. A module is loaded with import module and i defined as "A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended. " (check documentation). from x import y does also do the import module but sets another namespace (see discussion here). What you can do is load your module and then set your namespace manually afterwards, this is what the from x import y syntax does. You can load a module with the path (in this example i want to load read_csv from pandas):
importlib.import_module(".io.parsers", "pandas")
(check the path with print(inspect.getmodule(read_csv).__name__))
Also a solution like jottbe mentioned in the commentary would be possible
The exact syntax to correspond to mischva11's answer, is as follows:
tempmod = importlib.import_module("x_mymodule")
y = x_mymodule.y
del tempmod # optionally delete the reference to the parent module
Imports only the attribute y from the module x_mymod, similar to from x_mymodule import y. You can get the ... as z functionality by assigning it to any name you want in the 2nd line of code.
I found it useful to delete the parent module from the namespace, when using this in a sub-module, to prevent cluttering up the namespace.
I think to get the import * function you'll have to iterate through the module's attributes and assign them to a named attribute. Here are two hints that help you get there:
How to list all functions in a Python module?
Set attributes of module from inside the module: https://stackoverflow.com/a/2933481/2453202

How does importing a function from a module work in Python?

I have a module some_module.py which contains the following code:
def testf():
print(os.listdir())
Now, in a file named test.py, I have this code:
import os
from some_module import testf
testf()
But executing test.py gives me NameError: name 'os' is not defined. I've already imported os in test.py, and testf is in the namespace of test.py. So why does this error occur?
import is not the same as including the content of the file as if you had typed it directly in place of the import statement. You might think it works this way if you're coming from a C background, where the #include preprocessor directive does this, but Python is different.
The import statement in Python reads the content of the file being imported and evaluates it in its own separate context - so, in your example, the code in some_module.py has no access to or knowledge of anything that exists in test.py or any other file. It starts with a "blank slate", so to speak. If some_module.py's code wants to access the os module, you have to import it at the top of some_module.py.
When a module is imported in Python, it becomes an object. That is, when you write
import some_module
one of the first things Python does is to create a new object of type module to represent the module being imported. As the interpreter goes through the code in some_module.py, it assigns any variables, functions, classes, etc. that are defined in that file to be attributes of this new module object. So in your example, the module object will have one attribute, testf. When the code in the function testf wants to access the variable os, it looks in the function itself (local scope) and sees that os is not defined there, so it then looks at the attributes of the module object which testf belongs to (this is the "global" scope, although it's not truly global). In your example, it will not see os there, so you get an error. If you add
import os
to some_module.py, then that will create an attribute of the module under the name os, and your code will find what it needs to.
You may also be interested in some other answers I've written that may help you understand Python's import statement:
Why import when you need to use the full name?
Does Python import statement also import dependencies automatically?
The name testf is in the namespace of test. The contents of the testf function are still in some_module, and don't have access to anything in test.
If you have code that needs a module, you need to import that module in the same file where that code is. Importing a module only imports it into the one file where you import it. (Multiple imports of the same module, in different files, won't incur a meaningful performance penalty; the actual loading of the module only happens once, and later imports of the same module just get a reference to the already-imported module.)
Importing a module adds its name as an attribute of the current scope. Since different modules have independent scopes, any code in some_module cannot use names in __main__ (the executed script) without having imported it first.

What's the correct way for importing the whole module as well as a couple of its functions in Python?

I know that from module import * will import all the functions in current namespace but it is a bad practice. I want to use two functions directly and use module.function when I have to use any other function from the module. What I am doing currently is:
import module
from module import func1, func2
# DO REST OF MY STUFF
Is it a good practice? Does the order of first two statements matter?
Is there a better way using which I can use these two functions directly and use rest of the functions as usual with the module's name prepended to them?
Using just import module results in very long statements with a lot of repetition if I use the same function from the given module five times in a single statement. That's what I want to avoid.
The order doesn't matter and it's not a pythonic way. When you import the module there is no need to import some of its functions separately again. If you are not sure how many of the functions you might need to use just import the module and access to the functions on demand with a simple reference.
# The only import you need
import module
# Use module.funcX when you need any of its functions
After all, if you want to use some of your functions (much) more than the others, as the cost of attribute access is greater than importing the functions separately, you better to import them as you've done.
And still, the order doesn't matter. You can do:
import module
from module import func1, func2
For more info read the documentation https://www.python.org/dev/peps/pep-0008/#imports
It is not good to do (may be opinion based):
import module
from module import func1, func2 # `func1` and `func2` are already part of module
Because you already hold a reference to module.
If I were you, I would import it in the form of import module. Since your issue is that module.func1() becomes too long. I may import the module and use as for creating a alias for the name. For example:
import module as mo
# ^ for illustration purpose. Even the name of
# your actual module wont be `module`.
# Alias should also be self-explanatory
# For example:
import database_manager as db_manager
Now I may access the functions as:
mo.func1()
mo.func2()
Edit: Based on the edit in actual question
If your are calling same function in the same line, there is possibility that your are already doing some thing wrong. It will be great if you can share what your that function does.
For example: Want to the rertun value of those functions to be passed as argument to another function? as:
test_func(mo.func1(x), mo.func1(y). mo.func1(z))
could be done as:
params_list = [x, y, z]
func_list = [mo.func1(param) for param in params_list]
test_func(*func_list)

python import all modules to a python file which we can import in another file?

i'm new to python. i've some python scripts where in need to import different python modules.
Is it possible to
import all modules to one single file, say modules.py
and import this modules.py to all scripts, so that no need to import modules to each script ?
Thanks in advance
In mymodules:
import module1
import module2
in app:
from mymodules import *
But is it really worth it? The Zen of python states:
Explicit is better than implicit.
Copying some lines at the top of a file isn't really too much trouble.
There are at least 4 Ways to Import a Module:
import X, imports the module X: this way you can use X.whatever to refer to things defined in module X.
from X import *, imports the module X: this way you can simply use a plain name to refer to things defined in module X.
from X import x, y, z: you can now use x and y and z in the current name space.
X = __import__(‘X’) works like import X but this time the module name is a string. Use it it you don't know the module name before execution.
Think about namespace as a Python dictionary structure, where the dictionary keys represent the names and the dictionary values the object itself. Using import you can name the module inside your namespace.
That's said, you can perfectly import the modules inside a script (name it importer os something), and then import "importer" and everything will be inside your namespace.
Is that a good idea?, probably no because is common to found the same name (method, function or whatever) inside different modules and if that happens then ambiguity appears.

Categories