Python functions in separate file structure cannot be called - python

I have tried to organize my Python (Python version 3.9.2) project better and have created following file structure (I am using VS Code on Macbook Air M2). When I try to call a function in the "function file structure" I get the following error message:
NameError: name 'getAssetHoldings' is not defined
# File structure:
# main.py
my_functions
_init_.py
stock_functions.py
utility_functions.py
# Content of files:
#main.py:
import my_functions
import pandas as pd
import seaborn as sns
# load transaction file
filepath_transact = os.path.abspath(f"/Users/Sandbox/Data/transactions.csv")
df_sq = pd.read_csv(filepath_transact,encoding = "ISO-8859-1",sep=';')
# get asset holdings (function resides in stock_functions.py)
df_assets = getAssetHoldings(df_sq)
print('Assets:', '\n',df_assets,'\n')
#_init.py:
from .stock_functions import *
from .utility_functions import *
print('hello')
#stock_functions.py:
import pandas as pd
import yfinance as yf
import pandas_market_calendars as mcal
def getAssetHoldings(df):
df_numberAssets_k = df_transactions[df_transactions['Transaktionen'].isin(['Buy'])]
df_numberAssets_k = df_numberAssets_k[['Symbol','Quantity']]
df_numberAssets_v = df_transactions[df_transactions['Transaktionen'].isin(['Sell'])]
df_numberAssets_v = df_numberAssets_k[['Symbol','Quantity']]
....
return df_current_assets
I tried to restart the kernel and import the libraries and functions several times.

To close this question, I write here the solutions proposed in the comments.
To be more clear I re-write the main structure of the question:
│
├─ main.py
│
└─ my_functions/
├─ _init_.py
├─ stock_functions.py
└─ utility_functions.py
As #Roberto stated, the problem was that the __init__.py file needs the double underscore. And inside the main.py file, the function has to ba called through the dot notation my_functions.getAssetHoldings(...) since the module is imported with the line import my_functions.

Related

Create a python module with correct import arguments

Im trying to better understand the structure of a module that is imported with init.py files so I can apply it to my project.
I have this structure:
+ process.py
/packagename
/subpackage
+ __init__.py
+ subscript1.py
+ __init__.py
+ script1.py
+ script2.py
process.py:
import packagename
script1.py:
from script2 import Script2Class
script2.py:
from subpackage.subscript1 import SubScript1Class
init.py of /packagename :
from .subpackage import *
from .script1 import *
from .script2 import *
init.py of /subpackage:
from .subscript1 import *
Question1
When I import packagename it gives me this error:
File "process.py", line 1, in <module>
import packagename
File "C:\Users\du-mul\PycharmProjects\PakageTesting\packagename\__init__.py", line 4, in <module>
from .script1 import *
File "C:\Users\du-mul\PycharmProjects\PakageTesting\packagename\script1.py", line 1, in <module>
from script2 import Script2Class
ModuleNotFoundError: No module named 'script2'
That happens with script2.py too: He cant find the subpackage.
Why does Script1 not find Script2 even though they are in the same folder?
I can fix that mistake my applying this:
from packagename.script2 import Script2Class
However, then I cant execute script2.py on its own.
How should I write the imports correctly?
Question2
Do I need to import Script2 in the first init file in the first place? (Since only Script1 is using it)
Question3
When I import the subpackage there are 2 ways that work :
from .subpackage1 import *
or
import packagename.subpackage1
Which one should I use?
Do both import arguments make use of the subpackages init file?
Any help is appreciated

How to fix name is not defined in Python

I am running a python project like this:
project
Test.py
COMMON.py
SYSTEM.py
PTEST1
Hello.py
when run the code "Test.py" it will show NameError, I am not sure why?
But if I replaced the "from SYSTEM import *" with "from COMMON import *" in Test.py and PTEST1/Hello.py, it works as expect.
#Test.py is like this:
from SYSTEM import *
myvalue.Hello.printf()
# COMMON.py is like this:
myvalue = lambda: None
from PTEST1.Hello import Hello
myvalue.Hello = Hello
# SYSTEM.py is like this:
from COMMON import *
#PTEST1/Hello.py
from SYSTEM import *
class Hello():
#staticmethod
def printf():
print("Hello1")
print(vars(myvalue))
I expect there is no "NameError" by not changing import code. BTW, my python is 3.6+
Good practice is to give filenames in lowercase.
It looks like you are creating a Python project under project/. Any directory needs to have a file __init__.py in every directory in order for it to be discovered in Python.
You then need to refer to modules by their full name (not relative naming).
So the directory structure should be:
project/
__init__.py
test.py
common.py
system.py
ptest1/
__init__.py
hello.py
Every time you refer to file you should give the full path.
# import everything from hello.py
from project.ptest1.hello import *
# import everything from common.py
from project.common import *
# import everything from system.py
from project.system import *

__init__.py not working correctly in python

i want to make a sample package in python 2.7 just to clear my concepts whose structure looks like this:
calculator/
main.py
operations/
file1.py
file2.py
__init__.py
new_operations/
__init__.py
file3.py
main.py content: (this file is present inside calculator folder)
from operations import power
print power(2,2)
__init__.py content: (this file is present inside operations folder)
from .file1 import add
from .file1 import sub
from .file2 import mul
from .file2 import div
file1.py content: (this file is present inside operations folder)
def add(a,b):
return(a+b)
def sub(a,b):
return(a-b)
file2.py content: (this file is present inside operations folder)
def mul(a,b):
return(a*b)
def div(a,b):
return(a/b)
__init__.py content: (this file is present inside new_operations folder)
from .file3 import power
file3.py content: (this file is present inside new_operations folder)
def power(a,b):
return(a**b)
Now, when i run main.py, i got following error:
Traceback (most recent call last):
File "C:\Python27\mycodes\calculator\main.py", line 3, in <module>
from operations import power
ImportError: cannot import name power
Can anyone tell me, what mistake i am doing ? Help me.
Use the following line in your "main.py" file:
from operations.new_operations import power
You are missing an 'add' function in your calculator module. If you create an 'add' function, I would assume that the code would work.
maybe try doing this in the module calculator:
def add(num1,num2):
print(num1+num2)
return num1+num2;
If you don't want it to print while calculating, remove the print statement.
Hope this helps!

How do I load all modules under a subdirectory in Python?

I place my frequently used modules in a subdirectory lib/ and expect to load all modules into main.py by: (refer to Python: how to import from all modules in dir?)
from lib import *
but encounter the issue TypeError: 'module' object is not callable. More specifically, in main.py:
#!/usr/bin/env python
from lib import * # cause: TypeError: 'module' object is not callable
#from lib.DominatingSets import * # it works
dominatingSets = DominatingSets()
The full exception traceback:
$ python main.py
Traceback (most recent call last):
File "main.py", line 6, in <module>
dominatingSets = DominatingSets()
TypeError: 'module' object is not callable
The directories in a tree-like format.
$ tree -P '*.py' .
.
├── __init__.py
├── lib
│ ├── AnalyzeGraph.py
│ ├── AutoVivification.py
│ ├── DominatingSets.py
│ ├── __init__.py
│ ├── Output.py
│ ├── PlotGraph.py
│ ├── ProcessDatasets.py
│ └── ReadGTFS.py
├── main.py
The contents of lib/__init__.py are as follows. (refer to Loading all modules in a folder in Python)
from os.path import dirname, basename, isfile
import glob
modules = glob.glob(dirname(__file__)+"/*.py")
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not basename(f).startswith('__')] # exclude __init__.py
This confusion happened, in part, because your module names are the same as the names of the classes you want to load from them. (At least, that's what makes it more confusing.) Your code does correctly load the modules that your classes are in. However, it doesn't load the classes out of those modules, and this is what you actually wanted to do.
Because your class DominatingSets is in the module lib.DominatingSets, its full path from root is lib.DominatingSets.DominatingSets.
from lib import *
in your case will do the same thing as
from lib import DominatingSets
from lib import AnalyzeGraph
# ...
However,
from lib import DominatingSets
is equivalent to
import lib.DominatingSets
DominatingSets = lib.DominatingSets
but lib.DominatingSets is a module (lib/DominatingSets.py), not the class you want.
from lib.DominatingSets import DominatingSets
is equivalent to
import lib.DominatingSets
DominatingSets = lib.DominatingSets.DominatingSets
which is why it works: this is the class you want imported into the name DominatingSets.
If you want to have from lib import * import all the classes in the submodules, you need to import these classes into the lib module. For example, in lib/__init__.py:
from DominatingSets import *
from AnalyzeGraph import *
# ...
While you're making changes, I'd suggest (as others have) using normal Python naming conventions, and have your module names in lowercase: change DominatingSets.py to dominatingsets.py. Then this code would become
from dominatingsets import *
from analyzegraph import *
# ...
Looking at your Traceback, I think your problem might lie here:
Firstly, lets look at an example:
import datetime
d = datetime(2005, 23, 12)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'module' object is not callable
Basically, we've just imported the entire datetime module, and we're trying to call it like a class object within a module. Let's now do:
k = datetime.datetime(2005, 12, 22)
print k
2005-12-22 00:00:00
No problems this time, as we are referencing the datetime object type within the datetime module
If we do:
from datetime import datetime
datetime
<type 'datetime.datetime'>
Again we reach the desired object, as we are importing the datetime class within the datetime module.
Also, using *
from datetime import *
d = datetime(2005, 3, 12)
will also work, as you are importing all the classes within the datetime module.
Your code saying:
from lib import * # This imports all MODULES within lib, not the classes
#from lib.DominatingSets import * # it works because you import the classes within the DominatingSets Module
You could either use from lib.DominatingSets import DominatingSets which should solve your problem, or if you stick to from lib import *, change your code to dominatingsets = DominatingSets.DominatingSets()
Hope this helps!
I learnt a lot from the accepted answer here ... but I still had problems with what to put in the lib/__init__.py file, if this directory lib is not actually included in PYTHONPATH.
I found that in addition to adding the parent directory of lib in the caller file, i.e.
sys.path.append( '.../parent_dir_of_lib' )
I either 1) had to do this in addition in the caller file:
sys.path.append( '.../parent_dir_of_lib/lib' )
Or 2) had to make the lib directory "self-loading", by putting this in its __init__.py:
import sys
from pathlib import Path
parent_dir_str = str( Path(__file__).resolve().parent )
sys.path.append( parent_dir_str )
from analyse_graph import *
from auto_vivification import *
...

Python - Relative import does not work

My project structure:
project1/
__init__.py
main/
__init__.py
{main}.py
file1.py
file2.py
subA/
__init__.py
{moduleA}.py
class {A_class}
file3.py
file4.py
subB/
__init__.py
{moduleB}.py
file5.py
file6.py
I want to import {muduleA}.py in {moduleB}.py. Why cannot do this attempt?
in {moduleB}.py...
from project1.subA import {moduleA}
(not work as well followings..)
from ..subA import {moduleA}
from ..subA.{moduleA} import {A_class}
from project1.subA.{moduleA} import {A_class}
import project1.subA.{moduleA}.{A_class}
solved as following
import sys,os
sys.path.append(os.path.abspath('../../..'))
import project1.subA.moduleA.A_class
from project1.subA.moduleA import A_class
It will be better to import module explicitly to avoid confusing in the future.

Categories

Resources