Where to include import statements referenced in module functions? - python

I'm working on my first project and am trying to figure out how something works. If I have a module that store some functions I will reference in my main program that depend on another module, where do I include the import statement?
For example:
# Title: func.py
import os
def my_function(path):
if not os.path.isfile(path):
parser.error(f'The file {path} does not exist.')
Do I include import os here, or can I simply have it in the main document?

You must import the module in the file that references the module. So if you have a file that somewhere calls os.path.isfile, you need to import os at the top of that file.
-- comment by larsks

Related

Why is it not valid to write "from os import path.isfile, path.isdir, scandir"?

Is there another way to write it other than doing it in two separate lines like this?
from os.path import isfile, isdir
from os import scandir # or import os.scandir
TL;DR You can't. You got only that method from os.path import <stuff> if you wanna import the functions/objects from inside of os.path.
When you import stuff using just import you can import only modules (module is a term for python file containing python objects). To import the objects inside of a module you use from to traverse upto that module, and then you use import <whateverObject> to import that object from that file (anything and everything is an object in python, as long as it's inside a .py file). The . you use is (generally) to traverse through the directories ('sub' packages?) inside of a package.
How does the interpreter know which directory to include in a package, or how to recognise a given directory as a package? It looks for an __init__.py file inside it. If it finds one, it is a package, and thus you can import it.
import is limited to accessing directories and modules at most, if used alone. When you use from <module_or_directory> import <objects>, the task of accessing directories and/or modules is handed over to the clause after from, and the clause after import takes over the task of looking for python objects inside of the module. You see, these are two distinct things - 1) accessing a file/directory, which comes under file system, and 2) accessing the contents of a file, (specifically, a .py file), which comes under python's domain - neatly separated in the from-import style of importing stuff.
In the case of the os module, os.path is another .pyi file (ntpath.pyi on Windows) that is alias-ed in the os.py file as path. Since it is a module, it goes in the clause after from in from os.path import isfile, isdir. Whereas scandir is a function in os module, hence it goes in the clause after import in from os import scandir.

Cannot import function from another file

I have a file called hotel_helper.py from which I want to import a function called demo1, but I am unable to import it.
My hotel_helper.py file:
def demo1():
print('\n\n trying to import this function ')
My other file:
from hotel.helpers.hotel_helper import demo1
demo1()
but I get:
ImportError: cannot import name 'demo1' from 'hotel.helpers.hotel_helper'
When I import using from hotel.helpers.hotel_helper import * instead of from hotel.helpers.hotel_helper import demo1 it works and the function gets called. I tried importing the whole file with from hotel.helpers import hotel_helper and then call the function with hotel_helper.demo1() and it works fine. I don't understand what's wrong in first method. I want to directly import function rather using * or importing the whole file.
If you filename is hotel_helper.py you have to options how to import demo1:
You can import the whole module hotel_helper as and then call your func:
import hotel_helper as hh
hh.demo1()
You can import only function demo1 from module as:
from hote_helpers import demo1
demo1()
From your fileName import your function
from hotel.helpers import demo1
demo1()
You can import a py file with the following statement:
# Other import
import os
import sys
if './hotel' not in sys.path:
sys.path.insert(0, './hotel')
from hotel import *
NOTE:
For IDE like PyCharm, you can specify the import path using the Project Structure setting tab (CTRL+ALT+S)
Helpful stack overflow questions [maybe off topic]:
What is the right way to create project structure in pycharm?
Manage import with PyCharm documentation:
https://www.jetbrains.com/help/pycharm/configuring-project-structure.html
This is probably a duplicate of: https://stackoverflow.com/posts/57944151/edit
I created two files (defdemo.py and rundefdemo.py) from your posted 2 files and substituted 'defdemo' for 'hotel.helpers.hotel_helper' in the code. My 2 files are in my script directory for Python 3.7 on windows 10 and my script directory is in the python path file python37._pth. It worked.
defdemo.py
def demo1():
print('\n\n trying to import this function ')
rundefdemo.py
from defdemo import demo1
demo1()
output
trying to import this function
I was able to solve the issue, it was related to some imports I was making in my file, when I removed all the import statement in my hotel_helper.py ,the code started working as expected , Still I don't understand reason why the issue was occurring. anyway it works.
This ImportError can also arise when the function being imported is already defined somewhere else in the main script (i.e. calling script) or notebook, or when it is defined in a separate dependency (i.e. another module). This happens most often during development, when the developer forgets to comment out or delete the function definition in the body of a main file or nb after moving it to a module.
Make sure there are no other versions of the function in your development environment and dependencies.

Using modules imported from another import

I'm cleaning up a project that was refactored into smaller .py files. I noticed that a lot of modules are being imported again and again in various files. Some statements are in files that import another which has the same import statement used by the importing file. For example:
main.py
import alt
print (os.getcwd())
alt.py
import os
The print(os.getcwd()) throws a NameError: name 'os' is not defined. Shouldn't os be part of sys.modules when the import statement is executed in alt.py?
Is it possible to use a module imported by another module that was imported first?
They are available in the following namespace:
import alt
print (alt.os.getcwd())
To answer your immediate question, it is possible but not recommended.
Imports adjust the namespace in which they are made. This means that alt has an attribute os that can be accessed in main as
print(alt.os.getcwd())
This is not the recommended way, however, since it makes it less clear which actual os module you are using. You should do import os directly in main. This will not create a separate module object, so do not worry about cluttering your memory with duplicate modules.
The first time an import is encountered during runtime, it is added to the dictionary sys.modules, keyed by the fully qualified name of the module. Future import statements will look in sys.modules for an existing reference before doing any actual work.
In your case, import alt will create a module referenced by sys.modules['alt'] as well as by the name alt in main. The statement import os in alt will be run next. It will create a module referenced by sys.modules['os'] and alt.os. If you were to add a line import os in main after import alt, it will not create and load another module object. Instead, the name os will be bound to the same object pointed to by sys.modules['os'].
The following three versions of main will all call the same getcwd function:
Direct import (recommended):
import alt
import os
print(os.getcwd())
Use the reference in alt (harder to read/trace):
import alt
print(alt.os.getcwd())
Using sys.modules (really not recommended for production unless you know what you are doing):
import alt # necessary to trigger the actual import
import sys
print(sys.modules['os'].getcwd())
All imports load a full module. This even applies to imports of the form from os import getcwd. The module sys.modules['os'] is still created. The only difference is that the importing namespace will only have access to the name getcwd, not os. In your case, if alt contained from os import getcwd instead of import os, the three access methods would change as follows:
Unchanged.
print(alt.getcwd()) since alt.os no longer exists.
Unchanged.
You are importing os only in the in the submodul level of alt. os is to say so only available by access through alt.os. A way around this would be to import all from alt as from alt import *, but this is not what you should do...
As a general rule of thumb, you should re-import your directly called-to modules on the top level of the module that you currently process.
thus at main.py:
import os
and everything is fine
You write it this way
__author__ = 'kerberos'
__date__ = '2017/10/25 20:48 '
import alt
print(alt.os.getcwd())
This is the result:
C:\Users\Administrator\Desktop\11

Importing the same modules in different files

Supposing I have written a set of classes to be used in a python file and use them in a script (or python code in a different file). Now both the files require a set of modules to be imported. Should the import be included only once, or in both the files ?
File 1 : my_module.py.
import os
class myclass(object):
def __init__(self,PATH):
self.list_of_directories = os.listdir(PATH)
File 2 :
import os
import my_module
my_module.m = myclass("C:\\User\\John\\Desktop")
list_ = m.list_of_directories
print os.getcwd()
Should I be adding the line import os to both the files ?
How does this impact the performance, supposing there are lots of modules to be imported ? Also, is a module ,once imported, reloaded in this case ?
Each file that you are using a module in, must import that module. Each module is its own namespace. Things you explicitly import within that file are available in that namespace. Thus, if you need os in both files, you should import them in both files.

"Global name not defined" error

There are several posts around this error I have already read, but I still don't get what I am doing wrong.
I put it into a minimal example:
Imagine I have a Doc.py, and the package Tools which includes Tool1.py and Tool2.py.
Doc.py:
from Tools import *
import sys
def __main__():
TOOL_REPORT("Tool1","Test")
def TOOL_REPORT(tool, path):
if(tool == 'Tool1'):
Tool1.REPORT(path)
elif(tool == 'Tool2'):
Tool2.REPORT(path)
else:
sys.stderr.write("This tool is not yet included in Doc. Please check TOOLS for more information.")
if __name__=="__main__": __main__()
Tool1.py:
def REPORT(path):
print("Tool1 "+path)
Tool2.py:
def REPORT(path):
print("Tool2 "+path)
If I run this, I always end up with this error:
File "Doc.py", line 15, in TOOL_REPORT
Tool1.REPORT(path)
NameError: global name 'Tool1' is not defined
I'd appreciate any hint to what is going wrong!
Your Tool1 and Tool2 submodules are not visible until explicitly imported somewhere.
You can import them in the Tools/__init__.py package file:
import Tool1, Tool2
at which point they become available for import from Tools.
Another option is to import the modules from your own code:
import Tools.Tool1, Tools.Tool2
from Tools import *
Only when explicitly imported are submodules also set as attributes of the package.
Python will treat any folder as a module when there is __init__.py file present in it. Otherwise it will just be another folder for python and not a module from which it can import things. So just add init.py file in your Tool folder (so it will become module in pythonic terms) and then you can import that module in other python scripts.
One more things for better practice instead of using
from Tools import *
Always provide the file name of library specifically which you want to import like in your case you should use it like this
from Tools import Tool1, Tool2
This will enhance the code readbility for others and for you too.

Categories

Resources