I have the following project structure:
within blog_posts.py I have the following function and router:
# blog_post.py
router = APIRouter(
prefix="/blog",
tags=["blog"]
)
def required_functionality():
return {"message": "Learning FastAPI is important"}
within blog_get.py I also have a router and import the required_functionality function:
# blog_get.py
from blog_posts import required_functionality
router = APIRouter(
prefix="/blog",
tags=["blog"]
)
a = required_functionality()
Finally inside main.py im importing both routers:
# main.py
from router import blog_get, blog_posts
app = FastAPI()
app.include_router(blog_get.router)
app.include_router(blog_posts.router)
If I then run main.py I get the following error:
Traceback (most recent call last):
File "C:\Users\UKGC\PycharmProjects\FastAPI\Routers\main.py", line 6, in <module>
from router import blog_get, blog_posts
File "C:\Users\UKGC\PycharmProjects\FastAPI\Routers\router\blog_get.py", line 4, in <module>
from blog_posts import required_functionality
ModuleNotFoundError: No module named 'blog_posts'
If i then change the import in blog_get.py to:
# blog_get.py
from router.blog_posts import required_functionality
router = APIRouter(
prefix="/blog",
tags=["blog"]
)
a = required_functionality()
and run main.py again I have no issues, however, if I run blog_get.py directly I get the following error:
Traceback (most recent call last):
File "C:\Users\UKGC\PycharmProjects\FastAPI\Routers\router\blog_get.py", line 4, in <module>
from router.blog_posts import required_functionality
ModuleNotFoundError: No module named 'router'
How can I get main.py and blog_get.py to both work? I clearly don't seem to understand python imports properly, can someone explain what I'm missing?
I've tried converting router to a package, I've tried relative imports.
You should use relative imports, not absolute imports
# blog_get.py
from .blog_posts import required_functionality
When you execute main.py, there is no directory on your module search path that contains blog_posts.py. But there is a module router.blog_posts, and blog_get (which tries to import blog_posts) is in the package router as well.
To be able to run both scripts and get them to work I needed to append the 'router' to sys.path when importing from main.py. This is a bit of a hacky solution, im still open to other solutions?
# main.py
from router import blog_get, blog_posts
app = FastAPI()
app.include_router(blog_get.router)
app.include_router(blog_posts.router)
and
# blog_get.py
import os
import sys
fpath = os.path.dirname(__file__)
sys.path.append(fpath)
from blog_posts import required_functionality
router = APIRouter(
prefix="/blog",
tags=["blog"]
)
a = required_functionality()
I'm have a script 'zigbot.py' which was working, but I'm restructuring to dockerize and now I'm questioning my ability to code at all. What I'm trying to do is have a telegram-bot container, and a 'web' container (FLASK), and a nginx container.
Next to zigbot.py I have a folder - 'bot', which has many of my scripts and functions in. Upon trying from bot.somescript import a_function I am getting error after error.
Project structure
zigbot
bot
bot
__init__.py
conversations.py
ct.py
Docerfile
funcs.py
pricedata.py
requirements.txt
util.py
zigbot.py
nginx
somestuff
web
app
migrations
templates
__init__.py
config.py
forms.py
functions.py
models.py
routes.py
signals.py
__init__.py
Dockerfile
requirements.txt
zigweb.py
When running the code below, I get a whole range of strange errors - the one listed below shows ImportError - it can't find 'onboard' in funcs, but its definitely there. Before the restructure, this was working. If I comment out 'onboard' it errors on every function in the list.
from bot.conversations import key_conversation
from bot.crypto_functions import satoshi_to_btc
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
onboarded_message, blank_signal_message, send_signal_format, get_or_create_user, signal_detected_keyboard, log_me
Traceback (most recent call last):
File "zigbot.py", line 15, in <module>
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
File "ZigBot\bot\bot\funcs.py", line 2, in <module>
from zigbot.web.app import db, app
File "ZigBot\bot\zigbot.py", line 15, in <module>
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
ImportError: cannot import name 'onboard'
So I tried adding a .bot.conversation for (relative?) import, but this produces an even weirder error. I've included the code, the error, then the function I'm trying to import below:
from .bot.conversations import key_conversation
from .bot.crypto_functions import satoshi_to_btc
from .bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
onboarded_message, blank_signal_message, send_signal_format, get_or_create_user, signal_detected_keyboard, log_me
from ..web.app import db
from ..web.app.models import User, Signal
Traceback (most recent call last):
File "zigbot.py", line 13, in <module>
from .bot.conversations import key_conversation
ModuleNotFoundError: No module named '__main__.bot'; '__main__' is not a package
conversations.py
# Initialise conversationHandler states
def key_conversation(cancel):
# Define keyboards
keyboard = [
[InlineKeyboardButton('Previous', callback_data='onboard:key'),
InlineKeyboardButton('Next', callback_data='onboard:alldone')]]
conversation_keyboard = InlineKeyboardMarkup(keyboard)
Finally, I think I'm getting closer to the problem, I go back to the way I think it's supposed to be imported. From bot.funcs import x,y,y... I look in funcs.py and this is how its importing some other code from my Flask web app, but it doesn't like it.
funcs.py
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from web.app import db, app
from web.app.models import User
Traceback (most recent call last):
File "zigbot.py", line 15, in <module>
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
File "ZigBot\bot\bot\funcs.py", line 2, in <module>
from web.app import db, app
ModuleNotFoundError: No module named 'web'
So I change the import to go up a level since web is two levels above bot - which contains the script I'm importing to. So zigbot>bot>bot>funcs.py trying to import from zigbot>web>app>
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from ..web.app import db, app
from ..web.app.models import User
import telegram
Traceback (most recent call last):
File "zigbot.py", line 15, in <module>
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
File "\ZigBot\bot\bot\funcs.py", line 2, in <module>
from ..web.app import db, app
ValueError: attempted relative import beyond top-level package
This obviously doesn't work either. Given my structure of having bot and web how do I get this to work? I even tried pulling the scripts out of the second 'bot' folder but I get the same issues. Finally, my weirdest error which might provide a clue to what I'm doing wrong, if I change the import on funcs.py to go one level up, rather than two, I get an even stranger traceback.
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from .web.app import db, app
from .web.app.models import User
import telegram
Traceback (most recent call last):
File "zigbot.py", line 15, in <module>
from bot.funcs import onboard, main_menu, new_message1, new_keyboard, onboarded_keyboard, \
File "C:\Users\phill\PycharmProjects\ZigBot\bot\bot\funcs.py", line 2, in <module>
from .web.app import db, app
ModuleNotFoundError: No module named 'bot.web'
For clarity I removed some 'C:\Users\phill' from the tracebacks before realising it was pointless to remove that.
I think there's a fundamental flaw in your split if you have library dependencies across the boundary. Assuming that there are no imports of bot-modules in your web container, I would suggest breaking off the shared code into a module named weblib or something (alongside the bot-, nginx- and web-folders).
You still should not try to import across would-be container boundaries however, so just make sure weblib is in your path or installed in your virtual environment or however you want to handle it. Basically, bot and web should run in separate environments and should have weblib as a dependency.
Someone wiser than me might be able to explain it better.
For relative imports to work all the packages and subpackages must be in the sys.path - to achieve this you should run from the top-level directory as in:
C:\Users\phill\zigbot>python -m bot.zigbot
This will make your current working dir (zigbot) available to sys.path and the subpackages will be resolved correctly
I'm absolutely frustraded about the fact that I can't start my Python journey. I have a simple service which I use as a training with Python which is new for me.
I've downloaded PyCharm and as long as I had one file, everything was fine.
That I decided to to some structure and suddenly my project stopped working.
I have a structure like:
project/
project/employees
project/employees/__init__.py
project/employees/employees.py
project/server.py
project/venv/
project/venv/(...)
The project is a source root.
And yet I have something like this:
Traceback (most recent call last):
File "C:/Users/user/PycharmProjects/project/server.py", line 5, in <module>
from employees.employees import Employees, EmployeesName
File "C:\Users\user\PycharmProjects\project\employees\employees.py", line 4, in <module>
from server import db_connect
File "C:\Users\user\PycharmProjects\project\server.py", line 5, in <module>
from employees.employees import Employees, EmployeesName
ImportError: cannot import name 'Employees'
I tested this with VS Code and CMD and the same happend.
I would be grateful for any suggestions!
EDIT:
employees.py:
from flask_jsonpify import jsonify
from flask_restful import Resource
from server import db_connect
class Employees(Resource):
(...)
class EmployeesName(Resource):
(...)
The problem here is that you have a circular dependency.
In employees.py you import server.py; and vice versa.
You have to rearrange your .py files in order that not to happen anymore.
I have a basic parser app I'm building in Python. I monitors a folder and imports files when they are dropped there. I have a MongoDB that I'm trying to save the imports to. There's almost nothing to it. The problem happens when I try to include one of my class/mongo-document files. I'm sure it's a simple syntax issue I don't understand. I have all my requirements installed, and I'm running this in an virtual env. This is my first python app though, so it's likely something I'm not seeing.
My file structure is
application.py
requirements.txt
__init__.py
-services
parser.py
__init__.py
-models
hl7message.py
__init__.py
Here is application.py
from mongoengine import connect
import os, os.path, time
from services import parser
db = connect('testdb')
dr = 'C:\\Imports\\Processed'
def processimports():
while True:
files = os.listdir(dr)
print(str(len(files)) + ' files found')
for f in files:
msg = open(dr + '\\' + f).read().replace('\n', '\r')
parser.parse_message(msg)
print('waiting')
time.sleep(10)
processimports()
requirements.txt
mongoengine
hl7
parser.py
import hl7
from models import hl7message
def parse_message(message):
m = hl7.parse(str(message))
h = hl7message()
hl7message.py
from utilities import common
from application import db
import mongoengine
class Hl7message(db.Document):
message_type = db.StringField(db_field="m_typ")
created = db.IntField(db_field="cr")
message = db.StringField(db_field="m")
If I don't include the hl7message class in the parser.py it runs fine, but as soon as I include it I get the error, so I'm sure it has something to do with that file. The error message though isn't to helpful. I don't know if I've got myself into some kind of include loop or something.
Sorry, stack trace is below
Traceback (most recent call last):
File "C:/OneDrive/Dev/3/Importer/application.py", line 3, in <module>
from services import parser
File "C:\OneDrive\Dev\3\Importer\services\parser.py", line 2, in <module>
from models import hl7message
File "C:\OneDrive\Dev\3\Importer\models\hl7message.py", line 2, in <module>
from application import db
File "C:\OneDrive\Dev\3\Importer\application.py", line 23, in <module>
processimports()
File "C:\OneDrive\Dev\3\Importer\application.py", line 17, in processimports
parser.parse_message(msg)
AttributeError: module 'services.parser' has no attribute 'parse_message'
This is a circular import issue. Application.py imports parser, which imports h17 which imports h17message, which imports application which runs processimports before the whole code of the parser module has been run.
It seems to me that service modules should not import application. You could create a new module common.py containing the line db = connect('testdb') and import db from common both in application.py and in h17message.
So I have the endpoints_proto_datastore folder at the root of my project and yet I get this error each time I try to run it....
File "C:\pythonworkspace\...\endpoints_proto_datastore\utils.py", line 8, in <module>
from endpoints_proto_datastore.ndb import model
ImportError: cannot import name model
Anyone have any ideas?
I think you should use
from endpoints_proto_datastore.ndb import EndpointsModel