Import classes multiple times causes ImportError - python

Can anyone explain to me why I get the following error when running my programme please?
ImportError: cannot import name 'Adviser' from 'src.models.adviser'
My folder is structured like so...
root
-- src
models
-- __init__.py
-- adviser.py
-- episode.py
-- set_up.py
I have a setup script...
from src.models.adviser import Adviser
if __name__ == "__main__":
for adv in Adviser.all():
print(adv)
# src.models.adviser.py
from .base_model import BaseModel
from orator.orm import has_many
from .episode import Episode
class Adviser(BaseModel):
#has_many
def learners(self):
return Episode
and finally...
# src.models.episode.py
from .base_model import BaseModel
from orator.orm import belongs_to
from .adviser import Adviser
class Episode(BaseModel):
#belongs_to
def adviser(self):
return Adviser
If I remove the import statement from src.models.episode.py then the script runs.
What am I not understanding and doing wrong?

You have created circular imports: adviser imports Episode from episode, which in turn imports Adviser from adviser.
See more here:
Circular (or cyclic) imports in Python

Related

ImportError: attempted relative import with no known parent package/ Python/ unittesting

List item
I am trying to import the class Store from file grocery.py but am unable to do so using init.py.
Below is my file structure-
Main_folder
Grocery
__init__.py
grocery.py(which contains class Store())
tests
__init__.py
test_grocery.py
Codes are below:
test_grocery.py
'''
import unittest
from ..Grocery.grocery import Store
class TestCases(unittest.TestCase):
def test_cases_getSubTotal(self):
store1 = Store()
store1.activate()
self.assertTrue(store1.is_active())
def test_cases_getDiscount(self):
store2 = Store()
store2.add_points(25)
self.assertEqual(store2.get_points(), 25)
if __name__ == '__main__':
unittest.main()
'''
terminal
'''
from ..Grocery.grocery import Store
ImportError: attempted relative import with no known parent package
'''
Your import has to only contain the class_name.py and then import the function or class. Imports are also case sensitive.
from Grocery import Store
You cannot import from the parent directory unless you modify sys.path

Best practice for importing modules that contain imports

I tried to break up one large file into three smaller files for organization purposes and now nothing works. I'm sure the problem is with my import statements. Main.py imports Members.py and Members imports from RouteTools. However, even after including
import routeTools
...routeTools.tool()
In Members.py, it doesn't work after
Main.py
import Members
...Members.stuff()
I even tried putting
import routeTools
at the top of Main.py as well. What am I doing wrong or is there a better way to organize one file into multiple modules? Thanks.
Edit: "nothing works" = NameError: global name 'tool' is not defined when running routeTools.tool() from Members.py after it has been imported into Main.py
Here is my code:
import routetools
class Member(object):
def __init__(self, fields, scouts, id):
...
self.routes = [routeTools.Route(s) for s in self.scouts ]
...
And this is called in Main.py:
import Members
import routeTools
...
member = Members.Member(self.fields, self.scouts, i)
routeTools contains:
class Route(object):
...

Can't solve a circular import

I've read this good text as a reference, but I still can't solve my circular problem:
import pygame
import python
import background
import player
import parser
class Game():
map1 = parser.Parser("map1")
map1.parse()
The parser.py module:
import os, sys
def replaceExtension(mapPath):
# content
class Parser():
def __init__(self, map, path="Maps/"):
replaceExtension(path)
# content
When I run my main file:
map1 = parser.Parser("map1")
AttributeError: 'module' object has no attribute 'Parser'
For some obscure reason it just does not find my Parser class.
There is a built-in module called parser.
That's the one that gets imported. You need to rename your module.
You can find more on import order here: http://docs.python.org/2/tutorial/modules.html#the-module-search-path

Import Class to main script from subdirectory

I have a directory structure like this
main.py
markdown-extensions/
__init__.py
doc_extension.py
Here is my doc_extension.py (it's intended to be a bare bones markdown post processor):
from markdown.postprocessors import Postprocessor
class DocsPostProcessor(Postprocessor):
def run(self, text):
return "<h1>hello world</h1>"
class DocsExtension:
def extendMarkdown(self,md):
postProcessor = DocsPostProcessor()
postProcessor.md = md
md.postprocessors.add(postProcessor)
How do I go about importing it into my main.py? I've tried variations on the following to no avail:
import markdown-extensions.doc_extension
import markdown-extensions.*
import markdown-extensions.doc_extension
The - sign is not a valid character for a Python name (also known as identifier), whether it is a module or not. See here.
from markdown-extensions.doc_extension import *
but rather be explicit, as * will import all global variables, methods and classes. So:
from markdown-extensions.doc_extension import DocsPostProcessor, DocsExtension
*edit
And yes besides that you can't have "-"s, I mistook it for a "_".

Understanding python imports

In the process of learning Django and Python. I can't make sense of this.
(Example Notes:'helloworld' is the name of my project. It has 1 app called 'app'.)
from helloworld.views import * # <<-- this works
from helloworld import views # <<-- this doesn't work
from helloworld.app import views # <<-- but this works. why?
It seems like line #2 and #3 are practically the same. Why does like #2 not work?
Edit -- Added the source of the two files.
You might recognize this code from the Django Book project (http://www.djangobook.com/en/2.0)
helloworld/views.py
from django.shortcuts import render_to_response
from django.http import HttpResponse, Http404
import datetime
def hello(request):
return HttpResponse("Hello world")
def current_datetime(request):
current_date = datetime.datetime.now()
return render_to_response('current_datetime.html', locals())
def offset_datetime(request, offset):
try:
offset = int(offset)
except ValueError:
raise Http404()
next_time = datetime.datetime.now() + datetime.timedelta(hours=offset)
return render_to_response('offset_datetime.html', locals())
def display_meta(request):
values = request.META.items()
values.sort()
path = request.path
return render_to_response('metavalues.html', locals())
helloworld/app/views.py
from django.shortcuts import render_to_response
def search_form(request):
return render_to_response('search_form.html')
def search(request):
if 'q' in request.GET:
message = 'You searched for: %r' % request.GET['q']
else:
message = 'You searched for nothing.'
return render_to_response('search_results.html', locals())
Python imports can import two different kinds of things: modules and objects.
import x
Imports an entire module named x.
import x.y
Imports a module named y and it's container x. You refer to x.y.
When you created it, however, you created this directory structure
x
__init__.py
y.py
When you add to the import statement, you identify specific objects to pull from the module and move into the global namespace
import x # the module as a whole
x.a # Must pick items out of the module
x.b
from x import a, b # two things lifted out of the module
a # items are global
b
If helloworld is a package (a directory, with an __init__.py file), it typically doesn't contain any objects.
from x import y # isn't sensible
import x.y # importing a whole module.
Sometimes, you will have objects defined in the __init__.py file.
Generally, use "from module import x" to pick specific objects out of a module.
Use import module to import an entire module.
from helloworld.views import * # <<-- this works
from helloworld import views # <<-- this doesn't work
from helloworld.app import views # <<-- but this works. why?
#2 and #3 are not the same.
The second one imports views from the package helloworld. The third one imports views from the package helloworld.app, which is a subpackage of helloworld. What it means is that views are specific to your django apps, and not your projects. If you had separate apps, how would you import views from each one? You have to specify the name of the app you want to import from, hence the syntax helloworld.app.
As sykora alluded, helloworld is not in-and-of-itself a package, so #2 won't work. You would need a helloworld.py, appropriately set up.
I asked about import a couple of days ago, this might help:
Lay out import pathing in Python, straight and simple?

Categories