How importing actually works in python? - python

In my working directory, I have python3 files like this
/Path/to/cwd/main.py
/Path/to/cwd/Folder/one.py
/Path/to/cwd/Folder/two.py
So I had a main.py file like this
import Folder.one as one
#Do something
In one.py I had code like this
import two
#Some functions defined locally utilizing functions written in two.py
if __name__ == '__main__':
#Code for testing Functions
When I run one.py, it runs fine. But when I run main.py, it throws an error
ModuleNotFoundError: No module named 'two'
Ideally, I would not be expecting such an error at all.
It worked when I changed the import statement from import two to import Folder.two, which works. But I would like to do this in some other way without affecting such import statements much. How to achieve this?

In order for the python interpreter to know what directories contain code to be loaded, you need to include a __init__.py file.
Have a look at this answer to learn more about how to import packages.
In the case of your second import, to access that method you would need to use this syntax.
from .two import *

Related

Calling MATLAB functions inside a Python module

I have written a small Python module, with a single submodule. So far, life is good, and everything works. Here is a skeleton of the layout of said module
my_module/
__init__.py
setup.py
submod1/
__init__.py
my_matlab_fn.m
my_python.py
my_matlab_fn.m is a useful matlab function, which for the purposes of reproducing this example, may look like this:
Function Out = my_matlab_fn(x)
dummy = 2.0*x;
Out.val = dummy;
So far so good. Now, let's look inside my_python.py
import matlab
import matlab.engine
def double_my_t(t):
t_eng = matlab.engine.start_matlab('nodesktop -nosplash -nodisplay')
output = t_eng.my_matlab_fn(t)['val']
return output
if __name__ == '__main__':
print(double_my_t(4.0))
(In reality this is a simplified version of my actual code that I cannot show, in reality I am passing a dict to the matlab function and doing lots more operations with it).
OK. So, I am able to successfully do the following:
python3 my_python.py
when inside the submod1 directory. All is well and good and I get the correct result from this function call.
For context, here is what init.py looks like in the submod1 dir
from .my_python import double_my_t
and here is what init.py looks like in the my_module dir
from submod1.my_python import double_my_t
from submod1.my_python import double_my_t as double_my_t
I then go ahead and build my python module. Again, no issues here (have tested and seen my script successfully get inside the double_my_t function).
The issue is if I were to run something like this
from my_module.submod1 import double_my_t
print(double_my_t(4))
I get
matlab.engine.MatlabExecutionError: Undefined function 'my_matlab_fn' for inputs arguments ........
I think I understand what is going wrong, but I am not sure on this. I think that the reason why running my_python.py works is because matlab can 'see' the my_matlab_fn' function in 'my_matlab_fn.m' as this file is in the same dir as my_python.py when it is ran, and that when you try to call double_my_t from somewhere else outside this dir, then the matlab engine doesn't 'know' where my_matlab_fn.m is anymore.
I was wondering if anyone knew how I should resolve this issue. I want to be able to keep using these user-defined matlab functions in my Python module, however the documentation on this is not entirely clear.
Cheers

Cannot import name 'function' from 'module.py' - same directory, another function from the same module imports

I have a Jupyter Notebook - we'll call it main, and I'm running it piecemeal in Jupyter Lab 3.0.14 using a Python 3 environment.
Within this notebook, I'm trying to import custom functions from a module, we'll call this one module.py, which is in the same directory as main.
It looks something like this:
//main
import sys
import os
from module import foo, bar
//module.py
def foo():
return
def bar():
return
When I run the import statements in main, it throws an error
ImportError: cannot import name 'bar' from 'module' (/module.py)
If I run
from module import foo
or
from module import *
It's fine (although calling the functions will throw an error that the function is not defined). In fact, it will import foo even if there's no function named foo in module.py. It won't import any of my own functions by name. I feel like I must be missing something fundamental, here...
Any help would be greatly appreciated!!
Okay, this is my first time using Jupyter Lab, and this problem came from a fundamental misunderstanding of how Jupyter (and maybe other IDEs?) manages packages.
In short, as I understand it, re-running the code which imported functions from module.py did not actually re-import the contents. The only things it imported were what I asked for the first time, and any subsequent calls to import functions only referenced that first static image I pulled.
Therefore, if module.py had one function, foo, and I ran:
from module import foo
...then made some changes, such as editing the contents of foo and adding bar, running:
from module import foo, bar
...didn't actually do anything but reference that first copy of module.py I pulled. Because bar didn't exist the first time I ran the import function, it "couldn't see it", no matter how many times I re-ran the import function. I had to restart the kernel to fix it, basically.
I noticed this because when I changed the name of the script, it would import the functions that weren't previously working, but then edits to the functions, even once imported, weren't recognized.
This link provided the clue I needed to figure this out.
Hopefully this helps somebody!
Restart the kernel in the Jupiter notebook. I solved a similar import name issue by restarting the kernel.

"No module named..." with certain project structure

I have the following project structure:
MainScript.py
ExampleFolder
├ MainImport.py
└ SecondaryImport.py
MainScript.py: import ExampleFolder.MainImport
MainImport.py: Import SecondaryImport
When I try to run MainImport.py it gets no errors, but when I try to run MainScript.py, I get an import error that says No module named 'SecondaryImport'.
My question is simple - is there any way that I can import only MainImport.py from MainScript.py without getting this error, and importing SecondaryImport.py? Thanks in advance!
I have also tried adding a blank file named __init__.py to the ExampleFolder, but the error still appears. I also read Python's official documentation, but I could not find the problem. Am I missing something? (:
I think using the statement import ExampleFolder.SecondaryImport would work.
If it does, the error might be happening because as mentioned in docs, import statements will usually start searching your main project directory where the python interpreter was called if your module is not in python itself.
Another way would be to use relative import statement like this:
import .secondaryimport in order to tell the python interpreter to look in the current directory. Hope this helps!
Taking a look at these links will help, I think (It helped me when I was stuck in a similar problem):
https://docs.python.org/3/library/sys.html#sys.path
https://realpython.com/absolute-vs-relative-python-imports/
I have also tried adding a blank file named __init__.py to the ExampleFolder
That's the way - you're creating a Python package from a directory that way. And with packages you have got namespace directory.file where file is a Python file also known as module in Python world.
Then you can do from mainscript.py:
from examplefolder import mainimport
For importing inside package you may use the following syntax inside mainscript.py:
import secondaryimport
and use it in that mainscript.py as:
sevondaryimport.SomeClass()
or you may just do:
from secondaryimport import SomeClass
and use it like:
SomeClass()
Btw, use lowercase in all the cases except classes names - only they should have CamelCase names.

Python - How to allow the use of a function in different modules?

I have 2 scripts.
Main.py
Update.py
I have a function in Main.py which basically does the following:
def log(message):
print(message)
os.system("echo " + message + " >> /logfile.txt")
And in the Update.py file I have a single function which basically does the update. However throughout the update function, it calls "log(message)" with whatever the message is at that point.
The problem now though is I'm getting a NameError: global name "log" is not defined whenever I try use the function outside of the Main.py script.
Any help? on how I would be able to use the function 'log' wherever?
*Code simplified for explanation.
EDIT:
Main.py imports Update from /Scripts/Update.py
Update.py imports log from Main.py
When i try this, it fails saying "cannot import name Update"
Don't import log from Main. That'll rerun the code in Main.py, since running Main.py as a script and importing it as a module aren't equivalent. Other modules should not depend on functions defined in the main script. Instead, put your log function in another module and import that, or have Main.py explicitly pass a logger to the other modules somehow.
Update: You can't import Update because Python can't find it. Python checks in 4 places for modules to import, but the ones you should be interested in are
the directory the script was from, and
the directories specified in the PYTHONPATH environment variable.
You'll either need to put Main.py and the things it imports in the same directory, or add /Scripts to your PYTHONPATH.
Just add in Update.py the line
from Main import log
and you will be able to call log() from Update.py.
You should import the function:
from Main import log
Or best:
import Main
Main.log()
For modules importing each other, refer How can I have modules that mutually import each other.

how to execute nested python files

I have 3 python files.(first.py, second.py, third.py) I'm executing 2nd python file from the 1st python file. 2nd python file uses the 'import' statement to make use of 3rd python file. This is what I'm doing.
This is my code.
first.py
import os
file_path = "folder\second.py"
os.system(file_path)
second.py
import third
...
(rest of the code)
third.py (which contains ReportLab code for generating PDF )
....
canvas.drawImage('xyz.jpg',0.2*inch, 7.65*inch, width=w*scale, height=h*scale)
....
when I'm executing this code, it gives error
IOError: Cannot open resource "xyz.jpg"
But when i execute second.py file directly by writing python second.py , everything works fine..!!
Even i tried this code,
file_path = "folder\second.py"
execfile(file_path)
But it gives this error,
ImportError: No module named third
But as i stated everything works fine if i directly execute the second.py file. !!
why this is happening? Is there any better idea for executing such a kind of nested python files?
Any idea or suggestions would be greatly appreciated.
I used this three files just to give the basic idea of my structure. You can consider this flow of execution as a single process. There are too many processes like this and each file contains thousandth lines of codes. That's why i can't change the whole code to be modularize which can be used by import statement. :-(
So the question is how to make a single python file which will take care of executing all the other processes. (If we are executing each process individually, everything works fine )
This should be easy if you do it the right way. There's a couple steps that you can follow to set it up.
Step 1: Set your files up to be run or imported
#!/usr/bin/env python
def main():
do_stuff()
if __name__ == '__main__':
The __name__ special variable will contain __main__ when invoked as a script, and the module name if imported. You can use that to provide a file that can be used either way.
Step 2: Make your subdirectory a package
If you add an empty file called __init__.py to folder, it becomes a package that you can import.
Step 3: Import and run your scripts
from folder import first, second, third
first.main()
second.main()
third.main()
The way you are doing thing is invalid.
You should: create a main application, and import 1,2,3.
In 1,2,3: You should define the things as your functions. Then call them from the main application.
IMHO: I don't need that you have much code to put into separate files, you just also put them into one file with function definitions and call them properly.
I second S.Lott: You really should rethink your design.
But just to provide an answer to your specific problem:
From what I can guess so far, you have second.py and third.py in folder, along with xyz.jpg. To make this work, you will have to change your working directory first. Try it in this way in first.py:
import os
....
os.chdir('folder')
execfile('second.py')
Try reading about the os module.
Future readers:
Pradyumna's answer from here solved Moin Ahmed's second issue for me:
import sys, change "sys.path" by appending the path during run
time,then import the module that will help
[i.e. sys.path.append(execfile's directory)]

Categories