'function' object is not subscriptable in local package - python-3.x

While trying to learn how Python modules and packages work, I have the following error that I can't find a way around:
$ ./myMain.py
Traceback (most recent call last):
File "./myMain.py", line 6, in <module>
print(foobar.getKey['A'])
TypeError: 'function' object is not subscriptable
My directory structure is the following:
.
├── myMain.py*
└── utils/
└── Foo/
├── __init__.py
├── __pycache__/
│   ├── __init__.cpython-36.pyc
│   └── foobar.cpython-36.pyc
└── foobar.py
and myMain.py would be the main script from where the package would be imported. myMain.py has the following code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from utils.Foo import foobar
print(foobar.getKey['A'])
__init__.py is an empty file, and foobar.py has the function definition:
TEST_DICT = {
'A': 'This is A',
'B': 'This is B'
}
def getKey(letter):
return TEST_DICT[letter]
What am I doing wrong here?

After trying to run the code in myMain.py from within the Python interpret, I realised that the function call was writen with wrong syntax. Instead of foobar.getKey['A'] one should have instead foobar.getKey('A') because we are calling the function and not the dictionary object.

Related

import inside a python package - ModuleNotFoundError

I'm trying to build a package where specific modules call other modules. Example of the structure of the package:
provapackage/
├── main.py
└── pippo
├── derivative_functions.py
├── functions_pippo.py
└── __init__.py
content of the functions_pippo module:
def add(x,y):
return x+y
content of the derivative_functions module:
from functions_pippo import add
def add_lst(l):
n=0
for i in l:
n = add(n,i)
return n
content of the main.py file:
from pippo.derivative_functions import add_lst
lst = [1,2,3,4]
print(add_lst(lst))
when I run main.py I get this error:
Traceback (most recent call last):
File "/home/g/Documents/provapackage/main.py", line 1, in <module>
from pippo.derivative_functions import add_list
File "/home/g/Documents/provapackage/pippo/derivative_functions.py", line 1, in <module>
from functions_pippo import add
ModuleNotFoundError: No module named 'functions_pippo'
It seems like python cannot find the functions_pippo module even if it's in the same folder. But when I run derivative_functions.py I don't gat any error message. Is it an import problem?
See this answer here
from .functions_pippo import add
not
from functions_pippo import add

import between files (sibilins) of the same module (directory)

This is a tiny example of my question:
$ tree
.
├── mod
│   ├── a.py
│   ├── b.py
│   └── __init__.py
└── test.py
The code of test.py:
from mod import testB
if __name__ == '__main__':
testA()
testB()
The code of a.py:
def testA():
print("TEST A")
The code of b.py:
from a import testA
def testB():
print("TEST B CALLS TEST A")
testA()
The code of __init__.py:
from .a import *
from .b import *
And test.py fails when I call as it:
$ python3 test.py
Traceback (most recent call last):
File "test.py", line 1, in <module>
from mod import testB
File "/tmp/mod/__init__.py", line 2, in <module>
from .b import *
File "/tmp/mod/b.py", line 1, in <module>
from a import testA
ModuleNotFoundError: No module named 'a'
How do I change the __init__.py or b.py?

Python call module on other directory but not find module

I learning python module , I want to put some file to one mudole dir, and then call it at the project root. but it not work. I try to solve it , but it still not success!
what is the problem ?
├── calculator
│   ├── __init__.py
│   ├── addTwo.py
│   ├── mulTwo.py
│   └── sum.py
└── main.py
# calculator/__init__.py
#nothing
# calculator/addTwo.py
def addFunc(lhs, rhs):
return lhs + rhs
# calculator/mulTwo.py
def mulFunc(lhs, rhs):
return lhs * rhs
# calculator/sum.py
import addTwo
def sumFunc(arg1, arg2, arg3):
ans = addTwo.addFunc(arg1,arg2)
ans = addTwo.addFunc(ans,arg3)
return ans
#main.py
from calculator import addTwo
from calculator import mulTwo
from calculator import sum
def test():
print(addTwo.addFunc(1,2))
print(mulTwo.mulFunc(1,2))
print(sum.sumFunc(1,2,3))
if __name__ == '__main__':
test()
run it
cong.lin#C02YN3P4LVCK  ~/Program/python/module_test  python3 main.py
Traceback (most recent call last):
File "main.py", line 4, in <module>
from calculator import sum
File "/Users/cong.lin/Program/python/module_test/calculator/sum.py", line 1, in <module>
import addTwo
ModuleNotFoundError: No module named 'addTwo'
✘ cong.lin#C02YN3P4LVCK  ~/Program/python/module_test 
You have to provide PYTHONPATH to root of your project
Try
export PYTHONPATH=$PWD
before running
python3 main.py

Circular import despite absolute imports

I have got a problem with circular imports in Python 3.9.
I know there are numerous articles, questions and answers about this topic and I really have read a lot of them and about how to circumvent but I cannot figure out why it happens in my case. As far as I have understood one can circumvent circular imports by doing absolute imports:
This is my Stacktrace:
partially initialized module 'myproject.myapp.service.linepattern.corner' has no attribute 'Corner' (most likely due to a circular import)
File "/mnt/d/User/Programming/MyProject/myproject/myapp/service/linepattern/line.py", line 8, in Line
def __init__(self, cornerRight: cc.Corner, cornerLeft: cc.Corner) -> None:
File "/mnt/d/User/Programming/MyProject/myproject/myapp/service/linepattern/line.py", line 7, in <module>
class Line(ABC):
File "/mnt/d/User/Programming/MyProject/myproject/myapp/service/linepattern/corner.py", line 2, in <module>
import myproject.myapp.service.linepattern.line as cl
File "/mnt/d/User/Programming/MyProject/myproject/myapp/service/linepattern/cornermanager.py", line 2, in <module>
import myproject.myapp.service.linepattern.corner as cc
File "/mnt/d/User/Programming/MyProject/myproject/tests/myapp/test_cornermanager.py", line 3, in <module>
import myproject.myapp.service.linepattern.cornermanager as cm
and this is my file hierarchy
/mnt/d/User/Programming/MyProject
├── manage.py
├── myproject
│ ├── myapp
│ │ ├── __init__.py
│ │ ├── service
│ │ │ └── linepattern
│ │ │ ├── cornermanager.py
│ │ │ ├── corner.py
│ │ │ ├── line.py
│ │ │ ├── __init__.py
│ ├── settings.py
│ ├── tests
│ │ ├── myapp
│ │ │ ├── __init__.py
│ │ │ └── test_cornermanager.py
and finally my code
cornermanager.py
import myproject.myapp.service.linepattern.corner as cc
class CornerManager:
def __init__(self) -> None:
self.cornerList: List[cc.Corner]
for i in range(1, 2):
self.cornerList.append(cc.Corner(i, self))
for corner in self.cornerList:
corner.initializeLines()
def corner(self, cornerNr: int) -> cc.Corner:
return self.cornerList[cornerNr - 1]
corner.py
import myproject.myapp.service.linepattern.cornermanager as cm
import myproject.myapp.service.linepattern.line as cl
class Corner:
def __init__(self, cornerNumber: int, cornerManager: cm.CornerManager) -> None:
self.cornerNumber = cornerNumber
self.cornerManager = cornerManager
self.lineSet: Set[cl.Line]
def initializeLines(self) -> None:
#Add lines to the corner including its neighbor
if self.cornerNumber == 1:
self.lineSet.add(cl.Line(self, self.cornerManager.corner(2)))
elif self.cornerNumber == 2:
self.lineSet.add(cl.Line(self, self.cornerManager.corner(2)))
def addLine(self, line: cl.Line) -> None:
#Remove line from both corners
for corner in cl.cornerPair():
corner.lineSet.add(line)
def removeLine(self, line: cl.Line) -> None:
#Remove line from both corners
for corner in cl.cornerPair():
corner.lineSet.remove(line)
line.py
import myproject.myapp.service.linepattern.corner as cc
class Line:
def __init__(self, cornerRight: cc.Corner, cornerLeft: cc.Corner) -> None:
self.rightCorner = cornerRight
self.leftCorner = cornerLeft
def cornerPair(self) -> Tuple[cc.Corner, cc.Corner]:
#Return both corners
return (self.rightCorner, self.leftCorner)
With the code you put in the question (three separated modules), by including the following code at the top of each file should be able to fix the problems:
from __future__ import annotations
In short this code will treat annotations as strings. You can read more about this at: Type hint of the enclosing class and Evaluation of annotations.
For the errors, this actually how Python executes your modules (start from cornermanager.py):
import corner. With this Python first saves the module in its internal module (sys.modules) before running the imported module code.
In corner.py itself, the first two lines are import statement, so let's start with import cornermanager. Again, Python saves the module in its internal module then executes the code in cornermanager.
Back to cornermanager.py. As we know first line of this module is import corner, but because Python already saved this module (corner) in its internal module, it doesn't import it the second time. That is, Python skips it and executes code below this line. Interestingly, because corner hasn't executed all its code but the first line (import cornermanager), attempt to fetch its Corner class will not succeed.

How to properly import subpackages in python?

I have an import error I don't understand. I made a minimal example below, a small namespace package called p_parent which contains no __init__.py file but contains another sub-package called c_child
here is the full arborescence:
p_parent
├── c_child
│   ├── c_main.py
│   └── __init__.py
└── p_main.py
c_main.py and p_main.py contains almost nothing. p_parent/c_child/__init__.py contains only an import.
Here is the shell script which rebuilds this:
mkdir p_parent
mkdir p_parent/c_child
echo '#!/usr/bin/env python3\n\nc_value = 4\n' > p_parent/c_child/c_main.py
echo '#!/usr/bin/env python3\n\np_value = 4\n' > p_parent/p_main.py
echo '#!/usr/bin/env python3\n\nimport p_parent.c_child.c_main as c\n' > p_parent/c_child/__init__.py
When the content of the __init__.py file is import p_parent.c_child.c_main as c I get an error I don't understand when I try to import the submodule:
>>> import p_parent.c_child
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/C/autools/release/2019.09/scade/package/p_parent/c_child/__init__.py", line 3, in <module>
import p_parent.c_child.c_main as c
AttributeError: module 'p_parent' has no attribute 'c_child'
But, what tells me I missed something really important, is that when the content of the __init__.py file is only import p_parent.c_child.c_main everything works as expected (except I have loooong names)
>>> import p_parent.c_child
>>> p_parent.c_child.c_main
<module 'p_parent.c_child.c_main' from '/<snip>/p_parent/c_child/c_main.py'>
>>> p_parent.c_child.c_main.c_value
4
with from p_parent.c_child.c_main * it work somehow, but I would prefere to avoid it:
>>> import p_parent.c_child
>>> p_parent.c_child.c_value
4
What is the logic here ? Why the error is so unintuitive ?
python3.6 is used

Resources