Import class from folder python - python

Please don't immediately mark this as a duplicate question, because I have looked through loads of past questions with the same idea, but I don't understand any of the answers - they are bitty at best and involve making a file called init.py in the folder I think? I'm not sure.
So my specific problem is this: I am trying to write a program for blackjack. I have already created a class to create decks of cards in a separate file. I have everything in the same folder, called "classes". In this folder, there is:
- A file called __init.py (empty cause I don't know what it is supposed to do)
- A file called playingcardsclasses.py containing classes Card and Deck
- A file called blackjack.py which is where I am writing my main program.
I am using Pycharm, and it throws out a Traceback immediately, but still runs the code like I want - so I don't know why it is breaking.
The first line of my code is:
from playingcardsclasses.py import Deck
The traceback says:
Traceback (most recent call last):
File "(directory)/classes/blackjack.py", line 1, in
from playingcardsclasses.py import Deck
ModuleNotFoundError: No module named 'playingcardsclasses.py'; 'playingcardsclasses' is not a package
And then proceeds to run through the rest of my code happily, before finishing with a
Process finished with exit code 1
message - i.e. there is a problem here, hence the traceback.

Firstly, the syntax of your __init__.py file in your classes directory is incorrect. It should be __init__.py, not __init.py.
The reason for an __init__.py file in a directory is to tell python that this directory should be treated as a package. I.e., other .py files can be imported from this directory. (see here)
In your case, as your playingcardsclasses.py file contains the two classes, Card and Deck, you can import them from another file. Let's say you're in another file in the same directory called my_file.py. If you wanted to import the Deck class from playingcardsclasses.py, you would use:
from .playingcardsclasses import Deck
Note here that you should never use a trailing .py when importing, which is a mistake you made in your code block.
Edit: Also note the leading . in the import. This just specifies that the file playingcardsclasses.py is located in the same directory.

Related

Does a package 'see' itself in __init__.py?

I have a flask app with the root folder called project_folder.
A code snippet from the __init__.py file of this project_folder package:
#jwt.token_in_blacklist_loader
def check_if_token_in_blacklist(decrypted_token):
jti = decrypted_token['jti']
return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
from project_folder.Controller.root import root
from project_folder.Controller import auth_controller
from project_folder.Controller import item_controller
Now the interesting thing is, that the project_folder package naturally has other smaller packages itself, which I'm importing to use them (for REST resources in this example). These are the last 3 lines, nothing throws an error so far.
But, if you take a look at the annotated function (in this example it always runs before some kind of JWT Token is being used), I am returning some inner package's function. Now when the logic truly runs this part the code breaks:
PROJECT_ROUTE\project_folder\__init__.py", line 38, in check_if_token_in_blacklist
return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
NameError: name 'project_folder' is not defined
After thinking about it, it seems understandable. Importing from project_folder does import from the __init__.py file of the package, which is the actual file the interpreter currently is. So removing the package name prefix form the
return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
to
return Model.RevokedTokenModel.is_jti_blacklisted(jti)
does not throw an error anymore.
The question is: Why is it only a problem inside the callback function and not with the last 3 imports?
This has to do with circular imports in python. Circular import is a form of circular dependency, created at the module import level.
How it works:
When you launch your application, python keeps a register (a kind of table) in which it records all the imported modules. When you call somewhere in your code a module, python will see in its registry if it has already been registered and loads it from there. You can access this registry via sys.module, which is actually a dictionary containing all the modules that have been imported since Python was started.
Example of use:
>>> import sys
>>> print('\n'.join(sys.modules.keys()))
So, since Python is an interpreted language, reading and execution of code is done line by line from top to bottom.
In your code, you put your imports at the bottom of your __init__.py file.
While browsing it, when python arrives at the line return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti), it will look if the module exists in its register. Which is clearly not yet the case. That's why he raises an NameError: name 'project_folder' is not defined exception.

Module not found when importing package

Even after googling, trying a million things etc, I just can't get package importing to work properly. I have a simple folder structure like this:
(main folder)
---------------
funktio (folder)---->| __init__.py |
main.py | tulosta.py |
country_data.py ---------------
Basically I'm trying to import tulosta.py into main.py. Tulosta.py has a function that prints certain stuff from country_data.py. So far the program works when I paste the contents of tulosta.py into main.py and scrap the import of tulosta.py from main.py (so the script reads from country_data properly). I'm doing a school assignment and it requires importing a module and a package. My problem is, if I try to
import funktio.tulosta
I only get
Traceback (most recent call last):
File "E:\Kouluhommelit\Script-programming\moduuliharkka\main.py", line 4, in <module>
tulosta.tulosta()
NameError: name 'tulosta' is not defined
and if I try to put "from tulosta import tulosta" into the init file, I get
Traceback (most recent call last):
File "E:\Kouluhommelit\Script-programming\moduuliharkka\main.py", line 1, in <module>
import funktio.tulosta
File "E:\Kouluhommelit\Script-programming\moduuliharkka\funktio\__init__.py", line 1, in <module>
from tulosta import tulosta
ModuleNotFoundError: No module named 'tulosta'
So basically whatever I try I get an error code. Here's the code from main.py:
import funktio.tulosta
import country_data
tulosta.tulosta()
and tulosta.py:
def tulosta():
for code in country_data.countrycodes:
print (country_data.codemap[code], ':\n\t','Head honcho:', country_data.countries[country_data.codemap[code]]['head honcho'],'\n\t','Population:', country_data.countries[country_data.codemap[code]]['population'],'million')
I'm really getting desperate after struggling with this for 4+ hours already. It seems like such a simple operation, but apparently it isn't. Please help. I'll provide more info if needed.
Here's the assignment:
Rearrange the code from previous exercises:
Make a folder called "moduuliharkka"
Make a python file called "country_data" where you put the lists and dicts from the exercise 15.
Then make a new folder inside the moduuliharkka-folder called "funktio" (tip: init)
Put the code from exercise 16. inside a function and save it as a .py file in the funktio-folder
Go back to your moduuliharkka-folder, make a main.py file where you import the country_data module and the funktio folder as a package
Call the function imported in the main.py script
You need to make one extra call in your main file. Currently, you have imported the file tulosta from funktio, however, you need to access the function/class/variable in that file. tulosta.tulosta() is not including the folder name, which is still needed
In main:
import funktio.tulosta
functio.tulosta.tulosta() #call the function in "tulosta" here
If you do want to call tulosta() as tulosta.tulosta(), import with an alias:
import funktio.tulosta as tulosta
tulosta.tulosta()

Function call and file path confusion

I have two scripts, main and statistics. In one script, main, several functions from the other script, statistics, are called. The code is as follows.
if initial_action == "get_portfolio_statistics":
statistics.get_portfolio_status()
statistics.get_current_securities()
statistics.get_open_trades()
Of course, the functions match as far as calling names go, and my IDE (PyCharm) is not giving any warnings. Tests have, refactor after refactor, turned up the fundamentally same error report:
Traceback (most recent call last):
File "G:/stuff/dev/!projects+repositories/RYZ/main.py", line 2, in <module>
import statistics
File "G:\stuff\dev\!projects+repositories\RYZ\statistics.py", line 1, in
<module>
import main
File "G:\stuff\dev\!projects+repositories\RYZ\main.py", line 12, in <module>
statistics.get_portfolio_status()
AttributeError: module 'statistics' has no attribute 'get_portfolio_status'
There are, however, a few intriguing recurrences that have popped up. First of all, in some cases, for no identifiable reason, the tests check out when the function names are changed, however, the results are not consistent with further tests. Second of all, the use of back/forward slashes in the file paths are not consistent, with a G:/ with the first call, and then G:\ for the two latest calls, though the first and latest calls are referring to the same file.
My question is whether this error is a matter of function naming, a matter of file path inconsistencies, a matter of cross-imports, or due to the fact that the functions being called are not housed in a class.
Project Structure:
ryz server backend (RYZ directory)
- main.py
- statistics.py
Import Structure:
# in main.py
import statistics
# in statistics.py
import main
statistics.py Structure:
<imports...>
def get_portfolio_status():
<code>
def get_current_securities():
<code>
def get_open_trades():
<code>
I'll bet it's because of the cross-import. Try to move anything that statistics.py require to that file and then import into and call from main.py.
Your function naming is normal.
I wouldn't worry about the mix of slashes. However, if you're constructing a path yourself, use the os module:
import os
path = os.path.join(os.getcwd(), 'dir', 'filename')
This will ensure that you get a path suited to your platform.

Custom Python module structure

I am currently doing a personal coding project and I am trying to build a module, but I don't know why my structure doesn't work the way it's supposed to:
\mainModule
__init__.py
main.py
\subModule_1
__init__.py
someCode_1.py
someCode_2.py
\subModule_2
__init__.py
otherCode.py
I want to be able to run the following code from main.py:
>>> from subModule_1 import someCode_1
>>> someCode_1.function()
"Hey, this works!"
>>> var = someCode_2.someClass("blahblahblah")
>>> var.classMethod1()
>>> "blah blah blah"
>>> from subModule2 import otherCode
>>> otherCode("runCode","#ff281ba0")
However, when I try to import someCode_1, for example, it returns an AttributeError, and I'm not really sure why. Is it to do with the __init__.py file?
REVISIONS
Minimal, Complete and verifiable (I hope...)
\mainDir
__init__.py # blank file
main.py
\subDir
__init__.py # blank file
codeFile.py
Using this...
#main.py file
import subDir
subDir.codeFile.function()
And this...
#codeFile.py file
def function():
return "something"
...it returns the same problem mentioned above**.
** The exact error is:
Traceback (most recent call last):
File "C:\...\mainDir\main.py", line 2, in <module>
subDir.codeFile.function()
AttributeError: module 'subDir' has no attribute 'codeFile'
Credits to #jonrsharpe: Thanks for showing me how to use Stack Overflow correctly.
You have two options to make this work.
Either this:
from subdir import codeFile
codeFile.function()
Or:
import subdir.codeFile
subdir.codeFile.function()
When you import subDir, it does three things:
executes the code in mainDir/subDir/__init__.py (i.e. in this case does nothing, because this file is empty)
imports the resulting module under the name subDir locally, which will in turn make it an attribute of the mainDir module;
registers the new import globally in the sys.modules dictionary (because the import is being performed from a parent module mainDir, the name is completed to 'mainDir.subDir' for the purposes of this registration);
What it does not do, because it hasn't been told to, is import subDir.codeFile. Therefore, the code in codeFile.py has not been run and the name codeFile has not yet been imported into the namespace of mainDir.subDir. Hence the AttributeError when trying to access it. If you were to add the following line to mainDir/subDir/__init__.py then it would work:
import codeFile
Specifically, this will:
run the code in codeFile.py
add the resulting module as an attribute of the mainDir.subDir module
store a reference to it as yet another entry in sys.modules, this time under the name mainDir.subDir.codeFile.
You could also achieve the same effect from higher up the module hierarchy, by saying import subDir, subDir.codeFile instead of just import subDir in your mainDir.main source file.
NB: When you test this from the command line or IDE, make sure that your current working directory (queried by os.getcwd(), changed using os.chdir(wherever) ) is neither mainDir nor subDir. Work from somewhere else—e.g. the parent directory of mainDir. Working from inside a module will lead to unexpected results.

Python wont define function

I am getting back into python and I'm having a really basic issue....
My source has the following...
def calrounds(rounds):
print rounds
When I run this through the shell and try to call calrounds(3) I get..
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
calrounds(3)
NameError: name 'calrounds' is not defined
Its been awhile since I've used python, humor me.
Did you import your source first?
It says that the first line of your program is calling calrounds with a parameter 3. Move that below your function definition. The definition needs to be before you call the function. If you are using python 3.0+ you need parenthesis for the print statement.
>>> def calrounds(rounds):
print(rounds)
>>> calrounds(3)
3
The first thing to do is to look at how you're calling the function. Assuming it's in myModule.py, did you import myModule or did you from myModule import calrounds? If you used the first one, you need to call it as myModule.calrounds().
Next thing I would do is to make sure that you're restarting your interpreter. If you have imported a module, importing it again will not reload the source, but use what is already in memory.
The next posibility is that you're importing a file other than the one you think you are. You might be in a different directory or loading something from the standard library. After you import myModule you should print myModule.__file__ and see if it is the file you think you're working on. After 20 years of programming, I still find myself doing this about once a year and it's incredibly frustrating.
Finally, there's the chance that Python is just acting up. Next to your myModule.py there will be a myModule.pyc - this is where Python puts the compiled code so it can load modules faster. Normally it's smart enough to tell if your source has been modified but, occassionally, it fails. Delete your .pyc file and restart the interpreter.

Categories