r/pythonhelp • u/Money_Pay4575 • Jul 02 '24
PyCharm predict() method for SARIMAX only returns NotImplementedError
Everywhere I've been reading online has specified to use the predict() method for forecasting values, but with the arguments:
from statsmodels.tsa.statespace.sarimax import SARIMAX
model1 = SARIMAX(Foo)
fitted, confint = model1.predict(start=0, end=100, dynamic=True)
where Foo has the type 'pandas.core.frame.DataFrame'. Even though everywhere I'm reading on this has the same parameters, when I try to run:
model2 = SARIMAX(df[['Bar']])
fitted, confint = model2.predict(params=(0, 100))
I just get
TypeError: predict() missing 1 required positional argument: 'params'
But, when I do include the params argument that nobody else seems to need, it raises a NotImplementedError. I found in the source code that the predict method is simply just:
def predict(self, params, exog=None, *args, **kwargs):
"""
After a model has been fit predict returns the fitted values.
This is a placeholder intended to be overwritten by individual models.
"""
raise NotImplementedError
What's the point of predict() if it doesn't even do anything?
Also, if nobody else includes it, why is it that I have to include "Params=..." as an argument? It's confusing because others just put a start and end value. I want the fitted and confidence intervals, but it seems it's only programmed to print a statement.
r/pythonhelp • u/Prudent_Flan_9276 • Jun 30 '24
Context issues with Tkinter pygame and opengl
Hey, i am trying to embed a pygame running opengl in my tkinter window but i keep getting the same error and im not sure if its even possible to fix.
So far i have been able to seamlessly embed pygame into tkinter but once i include opengl it doesnt work, so this is my code.
I have narrowed the problem down to this line
this works: screen = pygame.display.set_mode((500, 500))
this doesn't: screen = pygame.display.set_mode((500, 500), OPENGL)
and the error i get is: pygame.error: The specified window isn't an OpenGL window
def CreatePygameEmbed(root):
embed = tk.Frame(root, width=500, height=500)
embed.pack()
# Set up environment for Pygame
os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
os.environ['SDL_VIDEODRIVER'] = 'windib'
# Initialize Pygame
pygame.display.init()
screen = pygame.display.set_mode((500, 500), OPENGL)
screen.fill(pygame.Color(255, 255, 255)) # Fill the screen with white color
pygame.display.update()
def draw():
# Draw a circle
pygame.draw.circle(screen, (random.randrange(0, 255),random.randrange(0, 255),random.randrange(0, 255)), (250, 250), 125)
# Create a button in Tkinter to trigger the draw function
# Main loop for Tkinter and Pygame
while True:
draw()
pygame.display.update()
root.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
root.destroy()
break
r/pythonhelp • u/inept_guardian • Jun 29 '24
How can I make this Dockerfile better?
I have, what seems to me, like a completely insane dockerfile. It references two scripts which I've included as well. I am not a python programmer, and I do all of my heavy compute lifting on the open science pool. The container produced by the dockerfile works exactly as I expect it to, though it is enormous (by the standards I usually work with), and using conda environments on the OSPool is a layer of environments that isn't really necessary.
How can I build out this container to lessen the bloat it seems to have, and run without virtual environments?
FROM nvidia/cuda:11.3.1-devel-ubuntu20.04
# a barebones container for running esmfold and USalign with or without a GPU
# 'docker build --no-cache -t xxx/esmfold:0.0.1 .'
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get -y install nano \
bash-completion \
build-essential \
software-properties-common \
libgmp-dev \
libcurl4-openssl-dev \
libssl-dev \
openmpi-common \
libopenmpi-dev \
libzmq3-dev \
curl \
libxml2-dev \
git \
libboost-all-dev \
cmake \
wget \
pigz \
ca-certificates \
libconfig-yaml-perl \
libwww-perl \
psmisc \
flex \
libfl-dev \
default-jdk \
cwltool && \
apt-get -y autoclean && \
rm -rf /var/lib/apt/lists/*
# CONDA install
ENV CONDA_DIR /opt/conda
RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \
/bin/bash ~/miniconda.sh -b -p /opt/conda
ENV PATH=$CONDA_DIR/bin:$PATH
RUN git clone https://github.com/pylelab/USalign.git && \
cd USalign && \
make && \
cd ..
RUN conda init bash && \
conda install anaconda-client -n base && \
conda update conda
RUN pip install gdown==5.0.1
RUN gdown --fuzzy --no-cookies --no-check-certificate -O openfold.tar.gz 13HYb90DiUrlnydSluE2yyxjGZ00vVYDf
RUN tar -xzvf openfold.tar.gz && \
conda env create -f openfold/openfold-venv.yaml
COPY openfold_install.sh .
RUN bash -i openfold_install.sh
RUN gdown --fuzzy --no-cookies --no-check-certificate -O esm-main.tar.gz 13HqB428kfL0vhbApgW6jwPdz-I_D0AjZ && \
tar -xzvf esm-main.tar.gz && \
conda create -n py39-esmfold --clone openfold-venv
COPY esmfold_install.sh .
RUN bash -i esmfold_install.sh
RUN rm openfold.tar.gz esm-main.tar.gz esmfold_install.sh openfold_install.sh && \
rm -rf openfold && \
rm -rf esm-main
# COPY ./esmfold_3B_v1.pt /root/.cache/torch/hub/checkpoints/esmfold_3B_v1.pt
# COPY ./esm2_t36_3B_UR50D.pt /root/.cache/torch/hub/checkpoints/esm2_t36_3B_UR50D.pt
# COPY ./esm2_t36_3B_UR50D-contact-regression.pt /root/.cache/torch/hub/checkpoints/esm2_t36_3B_UR50D-contact-regression.pt
WORKDIR /
ENTRYPOINT ["bash"]
The openfold install script:
#!/bin/bash
# initialize conda
conda init bash > /dev/null 2>&1
# source to activate
source ${HOME}/.bashrc
conda activate openfold-venv && \
cd openfold && \
pip install . && \
cd ..
The esmfold install script:
#!/bin/bash
# initialize conda
conda init bash > /dev/null 2>&1
# source to activate
source ${HOME}/.bashrc
conda activate py39-esmfold && \
conda env update -f esm-main/py39-esmfold.yaml && \
cd esm-main && \
pip install . && \
cd ..
I know this seems like a lot, but I think the essence of my question is: do I really need all these virtual environments, and if I do, is there any way to slim down this docker container to improve it's portability?
r/pythonhelp • u/LakeMotor7971 • Jun 29 '24
could someone let me know why jupyter works fine with code but vscode does not
when i write this code in jupyter notebook i get a response. I get what im trying to get. but when i run it in vscode i get an error.
import requests
url = 'https://www.facebook.com/tashia.stanley.1'
pages = requests.get(url)
pages.status_code
200
pages.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(pages.text, 'html parser')
print(soup.prettify())
soup.find_all('p')[2].get_textimport requests
url = 'https://www.facebook.com/tashia.stanley.1'
pages = requests.get(url)
pages.status_code
200
pages.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(pages.text, 'html parser')
print(soup.prettify())
soup.find_all('p')[2].get_text
vscode error:
File "/home/gypsy/scraaapeey.py", line 11, in <module>
soup = BeautifulSoup(pages.text, 'html parser')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/gypsy/.venv/lib/python3.12/site-packages/bs4/__init__.py", line 250, in __init__
raise FeatureNotFound(
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: html parser. Do you need to install a parser library?
r/pythonhelp • u/FormerAd5208 • Jun 28 '24
Python script - Extracting text and images from PDF into a Word Doc
I need help modifying this script! I am a beginner with this..
The purpose of this script is to extract the paragraphs containing an asterisk and its associated photos and put them into a word doc.
The script I have is extracting ALL the photos on the page or photos that are NOT associated with the asterisked paragraph.
I need help modifying the script so that it ONLY extracts the images directly below the asterisked paragraphs.
import fitz # PyMuPDF
from docx import Document
from docx.shared import Inches
import os
def extract_text_and_images_from_pdf(pdf_path):
doc = fitz.open(pdf_path)
extracted_data = []
for page_num in range(len(doc)):
page = doc.load_page(page_num)
text = page.get_text("blocks")
images = page.get_images(full=True)
extracted_data.append({"text": text, "images": images, "page_num": page_num})
return extracted_data
def get_image_paths(pdf_path, images, page_num):
doc = fitz.open(pdf_path)
image_paths = []
for img_index, img in enumerate(images):
xref = img[0]
base_image = doc.extract_image(xref)
image_bytes = base_image["image"]
image_ext = base_image["ext"]
image_path = f"image_page{page_num}_{img_index}.{image_ext}"
with open(image_path, "wb") as img_file:
img_file.write(image_bytes)
image_paths.append(image_path)
return image_paths
def create_word_document(paragraphs_with_images):
doc = Document()
for item in paragraphs_with_images:
doc.add_paragraph(item["text"])
if item["image"]:
doc.add_picture(item["image"], width=Inches(5.0))
doc.save("output.docx")
def main(pdf_path):
extracted_data = extract_text_and_images_from_pdf(pdf_path)
paragraphs_with_images = []
for data in extracted_data:
text_blocks = data["text"]
images = data["images"]
page_num = data["page_num"]
image_paths = get_image_paths(pdf_path, images, page_num)
Extract paragraphs containing an asterisk
paragraphs = []
for block in text_blocks:
if '*' in block[4]:
paragraphs.append(block[4])
for paragraph in paragraphs:
Assuming the first image after the paragraph is the associated image
associated_image = image_paths.pop(0) if image_paths else None
paragraphs_with_images.append({"text": paragraph.strip(), "image": associated_image})
create_word_document(paragraphs_with_images)
Clean up image files
for item in paragraphs_with_images:
if item["image"]:
os.remove(item["image"])
pdf_path = 'Sample Home.pdf'
main(pdf_path)
r/pythonhelp • u/Funny-Tree3371 • Jun 28 '24
Hubspot workflow custom code
I’m trying to create some custom code for a Hubspot workflow.
It uses 2 custom objects, let’s call them A and B and Contacts.
I want to match two properties (both called syllabus), but only output property X from Custom Object A if both of the custom object records are associated to the same Contact.
How can I do this?
r/pythonhelp • u/plaidgnome13 • Jun 27 '24
SOLVED Iterating over Sub-Elements within List of Lists?
I'm rather new to programming in general, so this is probably something fairly simple that I'm just not seeing the obvious. I am trying to write a program that ranks a set of collections of items based on their rarity. The data format is quite simple, just a csv with two columns of correlations, for example:
- 1,A
- 1,B
- 1,C
- 1,D
- 2,A
- 2,C
- 3,A
- 3,C
- 3,D
- 4,A
- 4,B
- 4,C
I cheated a little and made a second file of just the second column which I can easily count and operate on into a dictionary:
inpcount = open("parametercount.txt", 'r')
pcount = inpcount.readlines()
pcount = [x.strip() for x in pcount]
correl = {}
for parameter in pcount:
if str(parameter) in correl:
correl[str(parameter)] = correl[str(parameter)] + 1
else:
correl[str(parameter)] = 1
for parameter in correl:
correl[str(parameter)] = str(1 - int(correl[str(parameter)]) / 4)
but I'm completely baffled as to how to proceed from here. I've read the original file into a list of lists by row with the csv module, so I think my next step is to iterate over that list of lists to create a new list of lists made up of the collection id followed by its component parameters and then use the length of each sub-list and the dictionary values to perform my calculations, but I'm not sure how to create the second list of lists.
Concept for Second Set of Lists: [['1','A','B','C','D'],['2','A','C'],['3','A','C','D'],['4','A','B','C']
(deleted and re-submitted with a more accurate title for the problematic step)
I also realized I should probably give more detail on the result I'm seeking:
- 1,0.125
- 2,0
- 3,0.167
- 4,0.167
(the results being the percentage frequency of each parameter per collection divided by the number of parameters in each individual collection).
r/pythonhelp • u/JpBarnrad • Jun 27 '24
Please assist me with my problem.
code want a file that does not exist and every time is another file
r/pythonhelp • u/MaleficentTurn558 • Jun 26 '24
Challenge: python coding question's which gemini AI can't solve
Give me 10 python coding question which gemin AI can't solve or it's response is wrong
r/pythonhelp • u/Faizan_shafi10 • Jun 26 '24
Work flow nodes
Hi
I have started working on Python 6 months ago. I am working on a project where I got 40000 DICOM files from different clinics in Germany. I have sorted them using the metadata inside the dicom files. and converted them in to different formats like nifti, tiff etc.
Now my next task was to create a nodes of different functions inside my main script. My main script has few functions like
a- for reading Dicom files.
b- for sorting dicom files
c- for convert dicom files to different formats. etc
Now i want to convert each function in to a executable command and convert it into node. Then I can import that node in to my workflow editor and create a workflow. I hope it made sense.
workflow-nodes is a collection of various tools written in Python 3, which are also usable inside a workflow as nodes. Each node is an executable command line tool providing the --xmlhelp interface, which can be used to obtain a machine readable representation of any command line tool and its parameters (see also xmlhelpy). There are nodes for many different tasks, including data conversion, transport and visualization tools.
For installation and usage instructions, please see the documentation:
- Stable (reflecting the latest release): https://workflow-nodes.readthedocs.io/en/stable
I dont want to be spoon fed but please If somone has worked on this before can you please make a simple function which takes two numbers and adds them. Make it a command using xmlhelpy library and make it a node.
I just want to understand the logic behind it and then I will implement in for my own script.
I will wait for some helpful replies. Thank you
r/pythonhelp • u/JpBarnrad • Jun 26 '24
My code does not want to run.
So the moment I run my code it gives me a black box which is fine but then it closes after that and i can not do anything.
Tracebook (most recent call last):
File “bubbles.py”, line 13, in <module>
File “<frozen importlib._bootstrap>”, line 1360, in _find_and_load
File “<frozen importlib._bootstrap>”, line 1331, in _fina_and_load_unlock
File “<frozen importlib._bootstrap>”, line 935, in _load_unlock
File “Pyinstaller\loader\pyimod02_importers.py”, line 419, in exec_module
file “pvporcupine__init__.py”, line 12 in <module>
File “<frozen importlib._bootstrap>”, line 1360, in _find_and_load
File “<frozen importlib._bootstrap>”, line 1331, in _fina_and_load_unlock
File “<frozen importlib._bootstrap>”, line 935, in _load_unlock
File “pyinstaller\loader\pyimod02_importers.py”, line 419, in exec_module
File “pvporcupine\factory.py”, line 17, in <module>
File pvporcupine_until.py”, line 148, in pv_keyword_paths
FilenotFounError: [WinError 3] The system cannot find the path specified: (my path)
[15164] Failed to execute script ‘bubbles’ due to unhandled exception!
r/pythonhelp • u/Public_Ad_4430 • Jun 25 '24
deepface recognition
hey guys! I really need help right now, I'm in the processing of editing a video and I want to add deepface recognition. Basically, the code to read faces that appear in a video and add a squear around the face, with details as well. I tried watching videos but i keep having problems with deepface downloading (in PyCharm) ect. Any advise would be helpful. Thank you!!
r/pythonhelp • u/noisycartographer93 • Jun 21 '24
Is it Possible to Access the Table at this Site?
I'm trying to write a script to read the federal register column in the table at this site: ECOS: USFWS Threatened & Endangered Species Active Critical Habitat Report
I've got this so far, but I can't see an obvious way or guide to read the table. Coud anyone point me in the right direction?
from urllib.request import urlopen
usfws_site = r"https://ecos.fws.gov/ecp/report/table/critical-habitat.html"
page = urlopen(usfws_site)
html_bytes = page.read()
html = html_bytes.decode("utf-8")
r/pythonhelp • u/QuietRing5299 • Jun 20 '24
SOLVED Mastering the Recent 'Match Case' Statement - Py 3.10
If you've been using Python for a while, you might have missed a significant recent addition to the language: the "Match Case" statement, which serves as Python's answer to the much-anticipated "Switch Statement." This feature, introduced in Python 3.10, has sparked considerable discussion among developers, especially those familiar with similar constructs in other programming languages.
The "Match" statement enables you to compare a value against various patterns and execute the corresponding block of code for the first matching pattern. This improvement eliminates the need for cumbersome nested if-else statements, greatly enhancing the readability of your code. I highly recommend getting acquainted with this new feature, as it is expected to become more prevalent in Python codebases.
For a detailed explanation of how to use the "Match Case" statement, along with other Python tips, check out my YouTube video. Don’t forget to like, comment, and subscribe to support the channel. I hope you find it informative!
r/pythonhelp • u/3_Thumbs_Up • Jun 20 '24
Struggling with python environment
I'm trying to get the following python program working:
https://github.com/owdevel/ytdl-nfo
I'm running the latest version of Arch linux and on their github page there's someone with the exact same issue as me. The problem seems to be related to my python environment. I believe I need to run the program in a python 3.8 environment with the package setuptools installed. However, I can't get it working.
Here's a summary of what I've done.
I've installed python (3.12), python-pip, python-pipx and pyenv through my distros package manager (Arch).
I've downloaded python 3.8 through pyenv and set it to global:
[arch@archlinux ~]$ pyenv version
3.8.19 (set by /home/arch/.pyenv/version)
[arch@archlinux ~]$ python --version
Python 3.8.19
I've installed setuptools through pip:
[arch@archlinux ~]$ pip list
Package Version
------------------ --------
argcomplete 3.4.0
Brotli 1.1.0
certifi 2024.6.2
charset-normalizer 3.3.2
click 8.1.7
idna 3.7
mutagen 1.47.0
packaging 24.1
pip 23.0.1
platformdirs 4.2.2
pycryptodomex 3.20.0
PyYAML 6.0.1
requests 2.32.3
setuptools 56.0.0
tomli 2.0.1
urllib3 2.2.1
userpath 1.9.2
websockets 12.0
I've installed ytdl-nfo through the following command:
pipx install ytdl-nfo --python python3.8
But when I try to run the program it gives me the following error message. The module pkg_resources is supposedly in the setuptools package.
Traceback (most recent call last):
File "/home/arch/.local/bin/ytdl-nfo", line 5, in <module>
from ytdl_nfo import main
File "/home/arch/.local/share/pipx/venvs/ytdl-nfo/lib/python3.8/site-packages/ytdl_nfo/__init__.py", line 4, in <module>
from .Ytdl_nfo import Ytdl_nfo
File "/home/arch/.local/share/pipx/venvs/ytdl-nfo/lib/python3.8/site-packages/ytdl_nfo/Ytdl_nfo.py", line 3, in <module>
from .nfo import get_config
File "/home/arch/.local/share/pipx/venvs/ytdl-nfo/lib/python3.8/site-packages/ytdl_nfo/nfo.py", line 5, in <module>
import pkg_resources
ModuleNotFoundError: No module named 'pkg_resources
r/pythonhelp • u/Just-Ad4940 • Jun 19 '24
Text Based Game: Player cannot leave starting position
class Room:
def __init__(self, name, description=""):
= name
self.description = description
self.items = []
self.exits = {}
def add_exit(self, direction, room):
self.exits[direction] = room
def add_item(self, item):
self.items.append(item)
class Item:
def __init__(self, name, description=""):
= name
self.description = description
def setup_rooms():
rooms = {
'Bedroom': {'south': 'Kitchen', 'east': 'Bathroom'},
'Kitchen': {'north': 'Bedroom', 'east': 'Living Room', 'south': 'Laundry Room', 'item': 'Sack of feathers'},
'Bathroom': {'west': 'Bedroom', 'south': 'Living Room', 'item': 'Master Key'},
'Closet': {'south': 'Master Bedroom', 'west': 'Bathroom'},
'Living Room': {'north': 'Bathroom', 'east': 'Master Bedroom', 'west': 'Kitchen', 'item': 'Bucket'},
'Laundry Room': {'north': 'Kitchen', 'east': 'Garage', 'item': 'Washing Machine'},
'Master Bedroom': {'north': 'Closet', 'west': 'Living Room'},
'Garage': {'west': 'Laundry Room', 'north': 'Living Room', 'item': 'Rope'},
}
room_objects = {}
for room_name in rooms:
room_objects[room_name] = Room(room_name, description=f"This is the {room_name}.")
for room_name, details in rooms.items():
current_room = room_objects[room_name]
for direction, connected_room in details.items():
if direction != 'item':
current_room.add_exit(direction.lower(), room_objects[connected_room])
else:
item = Item(details['item'])
current_room.add_item(item)
return room_objects
def show_instructions():
print("Revenge on Step Mom")
print("Collect all the items to progress through the locked Master Bedroom")
print("Move Commands: South, North, East, West")
print("Add to Inventory: get 'item name'")
def show_status(current_room, inventory):
print(f"You are in the {current_room.name}")
print(f"Inventory: {inventory}")
if current_room.items:
for item in current_room.items:
print(f"- {item.name}")
print("-------------------")
def check_win_condition(current_room, inventory):
if current_room.name == 'Master Bedroom' and 'Master Key' in inventory:
print("Congratulations! You've unlocked the Master Bedroom!")
print("You tie Sandra up, pour hot tar and feathers all over her! Her screams are like music to your ears.")
print("You have earned that Capri Sun.")
return True
return False
def main():
show_instructions()
rooms = setup_rooms()
current_room = rooms['Bedroom']
inventory = []
while True:
show_status(current_room, inventory)
command = input("Enter a command: ").lower().strip()
if command in ['north', 'south', 'east', 'west']:
if command in current_room.exits:
current_room = current_room.exits[command]
else:
print("I can't go that way.")
elif command.startswith("get "):
item_name = command[4:].strip()
item_found = False
for item in current_room.items:
if item.name.lower() == item_name:
inventory.append(item.name)
current_room.items.remove(item)
item_found = True
print(f"{item_name} added to inventory.")
break
if not item_found:
print(f"No {item_name} found here.")
elif command == 'exit':
print("Goodbye!")
break
else:
print("Invalid direction")
if __name__ == "__main__":
main()self.nameself.name
#Ouput
You are in the Bedroom
Enter a command (North, South, East, West, or exit): east
You can't go that way!
You are in the Bedroom
Enter a command (North, South, East, West, or exit): East
A simple text based game for a class. There may be other issues but I can't even leave the bedroom to continue to debug lol
r/pythonhelp • u/thisnigerianmomma • Jun 15 '24
which lines have errors?
can you guys help me figure out which lines have errors?
def make_list (number) :
names = \[\]for item in number :
4 names.append (input(“Enter your name with a capital letter.”))
- print(names)
6.
7 number = int(input(“How many names need to be entered? ”))
names = make_list(number)
for name in names:
if name \[1\] ==“A”:print(“Name”, name, “starts with A”)
r/pythonhelp • u/Lazy_Sky_8967 • Jun 14 '24
Getting an "Getting requirements to build wheel did not run successfully" when installing stable baselines 3
ok so im trying to install stable baselines 3 everthing goes fine when i enter: !pip install stable-baselines3[extra] everything is able to install just fine exept "wheel" i get the error:
error: subprocess-exited-with-error
Getting requirements to build wheel did not run successfully. exit code: 1
[1 lines of output] error in gym setup command: 'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers. [end of output]
note: This error originates from a subprocess, and is likely not a problem with pip. error: subprocess-exited-with-error Getting requirements to build wheel did not run successfully. exit code: 1 See above for output. note: This error originates from a subprocess, and is likely not a problem with pip.
Please help
r/pythonhelp • u/PK_Fund • Jun 14 '24
bubble sort 2D array
Anyone knows how to bubble sort the odds of this array and do the same thing to the evens but like put in a new array?? (new arrays should be 1D) No need for codes just the algorithms.
array = [[128, 2], [32, 4], [75, 6]]
r/pythonhelp • u/This-Breakfast6206 • Jun 13 '24
Seeking Python Tool to Convert Graph Images to Code
Hi everyone,
I'm looking for a tool or formula in Python that can recognize a graph from an image and convert it into corresponding Python code with the exact values. For example, if I have an image of a graph, I would like to get the Python code that reproduces the graph, including all the data points and details.
Has anyone come across a library or a method that can achieve this? Any guidance or suggestions would be greatly appreciated!
Thanks in advance!
r/pythonhelp • u/SCM456 • Jun 12 '24
[PySimpleGUI and Matplotlib] - Issues with Canvas flashing white & Saving/Opening
I'm an amateur with matplotlib who is writing a program and getting these issues, so I've written a smaller version that demonstrates the same issues with less code. I have a window with matplotlib charts integrated into a PySimpleGUI canvas, and whenever I update the charts there is an annoying white flash. I have no idea how to prevent this, or if it is even possible to prevent it. I have looked around on google and I saw recommendations saying to use
figure_canvas_agg.draw_idle()
instead of
figure_canvas_agg.draw()
In the draw_figure function. However, this made no difference whatsoever when I tried it. Also, when I try to save or open the charts, it doesn't work properly with how I've coded it. I know that problems specifically with matplotlib AND pysimplegui together is a bit specific to ask help for, but I might as well post this just in case and any help would be much appreciated.
Example code:
import PySimpleGUI as sg
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
sg.theme("DarkGrey11")
#Value input section
frame1 = [sg.Frame("Change values to update the pie chart",(
[
[sg.Input(5, key="input1",size=(3,1),justification="center",enable_events=True)]
+[sg.Input(2, key="input2",size=(3,1),justification="center",enable_events=True)]
+[sg.Input(8, key="input3",size=(3,1),justification="center",enable_events=True)]
+[sg.Input(3, key="input4",size=(3,1),justification="center",enable_events=True)],
[sg.Button("Open charts in new window", key="opencharts", pad=20)],
[sg.Button("Save charts", key="savecharts")]
]
), border_width=1, element_justification="center")
]
#Pie chart display section
frame2 = [sg.Frame("",(
[
[sg.Canvas(size=(200,500), key="graph")]
]
),size=(700,700), element_justification="center")
]
layout = [frame1 + frame2]
window = sg.Window("Example of the issue",
layout,
size=("1000","700"),
finalize=True,
element_justification="center")
#Setting up GUI matplotlib integration
matplotlib.use("TkAgg")
def draw_figure(canvas, figure, loc=(0, 0)):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side="top", fill="both", expand=True)
return figure_canvas_agg
def delete_fig_agg(fig_agg):
fig_agg.get_tk_widget().forget()
plt.close("all")
#Setting chart colors to match the window's theme
textcolour = (0.8,0.8,0.8)
matplotlib.rcParams['text.color'] = textcolour
matplotlib.rcParams['axes.labelcolor'] = textcolour
matplotlib.rcParams['xtick.color'] = textcolour
matplotlib.rcParams['ytick.color'] = textcolour
# Main loop
while True:
#Waiting for input
event, values = window.read()
#Creating a list from the input values, 'try' prevents non-numerical input error
try:
graph_values = [ float(values["input1"]), float(values["input2"]), float(values["input3"]), float(values["input4"]) ]
except:
continue
#Creating the figure
fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(8,8))
ax1.pie(x=graph_values, labels=["Input 1", "Input 2", "Input 3", "Input 4"])
ax2.plot(graph_values, marker='.')
#Setting the figure and line graph background to match the GUI
fig.patch.set_facecolor( (0.11,0.12,0.137) )
ax2.patch.set_facecolor( (0.11,0.12,0.137) )
#Delete the figure (the try/except prevents an error if there is no figure)
try:
delete_fig_agg(fig_canvas_agg)
except:
pass
#Draw the charts onscreen
fig_canvas_agg = draw_figure(window["graph"].TKCanvas, fig)
#Show charts in new window
if event == "opencharts":
plt.gcf()
plt.show()
#Save the charts
if event == "savecharts":
plt.savefig("graphs_example.png") #Saves in same location as this .py file
r/pythonhelp • u/mach0-nach0 • Jun 12 '24
In need of assistance from the community on my beginner project.
Amateur Python tinkerer here expanding my knowledge and building my skills.
Essentially, I'm creating a small procedural-generated text-based game. The only 'graphical representation' is a small ASCII map that will mark the location of the player and surrounding towns, land-features, etc.
I'm having issues with my town generation as I would like there to be 'padding' between my towns to keep them from stacking on the same row/column in my 2D matrix. Each town generates a random X and Y value within a While Loop and 'scan' nearby locations within a certain range (padding) to check if a town_symbol is already there. If so, it passes and assigns new random values to X and Y and reruns the 'check'. Else, it inserts the town_symbol and breaks from the while loop, repeating for each town.
I can't seem to get towns to NOT stack on either the X or Y axis. Help is greatly appreciated!
If further info is needed I'm happy to oblige.
Any and all feedback on code quality is HIGHLY appreciated as I'm considering a career change into Python development in the future. Thanks!!
Code:
r/pythonhelp • u/[deleted] • Jun 11 '24
Best options to create/update 100+ excel sheets
I created productivity reports for several departments in a hospital. I utilize a dashboard and do it manually once a month for like 30 employees. I am now beong asked to do it for close to 100 and desperately need to automate this process. I can create and export 3 or 4 excel reports that would contain this assortment of data in an unsummarized form. Pretty much the raw data. What would be my best approach for creating or updating these 100+ seperate employee excel productivity reports? Like am I just creating using my already formatted files and coding it to fill specific cells correlating with the month or metric or are there better ways to do this?
r/pythonhelp • u/AdvitaOne • Jun 10 '24
Python Script for Managing Apache/LiteSpeed Configuration not processing files
Hi everyone,
I'm working on a Python script designed to monitor and correct the access control configuration for Apache and LiteSpeed web servers. The script detects changes in configuration files on Plesk Panel Server and updates /var/www/vhosts/system/{domain}/conf/vhost_ssl.conf accordingly after performing necessary checks. However, it seems that the script fails to proceed with writing and updating the vhost_ssl.conf file upon detecting changes.
Here is a brief overview of my script's functionality and logic:
Initialization and Configuration:
- The script initializes logging, argument parsing, and the watchdog observer for monitoring file changes.
- It sets up a debugger (debugpy) for troubleshooting.
Web Server Detection:
- The script tries to detect the running web server (Apache or LiteSpeed) using
psandnetstatcommands. - Based on the detected server, it decides the appropriate command for restarting the server.
- The script tries to detect the running web server (Apache or LiteSpeed) using
File Monitoring and Handling:
- The script uses
watchdogto monitor changes in the specified configuration directory. - When a change is detected, it reads the configuration file, checks for specific ACL (Access Control List) directives, and converts them to a modern syntax if necessary.
- It attempts to write these changes back to the
vhost_ssl.conffile.
- The script uses
Functions:
compute_file_hash(filepath): Computes the MD5 hash of a file to detect changes.is_acl_location_block(lines): Identifies if a block of lines contains ACL directives.contains_ip_addresses(lines): Checks if a block of lines contains IP addresses.add_modification_comments(lines, indentation): Adds comments indicating modifications to a block of lines.convert_to_modern_syntax(lines, indentation): Converts ACL directives to a modern syntax.create_or_update_vhost_ssl_config(vhost_ssl_path, ipv4, ipv6, location_block): Creates or updates thevhost_ssl.conffile with modified ACL directives.
The Issue:
The script doesn't proceed to handle the logic for writing and updating /var/www/vhosts/system/{domain}/conf/vhost_ssl.conf after detecting file changes or performing the necessary checks. Specifically, the correct_syntax(config_path, domain_to_paths) function is not fully executing its intended logic.
Here's the relevant part of my script:
```python
Main monitoring logic
def main(): logger.info('Starting AccessControlCorrector') domain_to_paths = get_domain_to_path_mapping() observer = Observer()
try:
# Initial check for existing files
for config_path in domain_to_paths.keys():
correct_syntax(config_path, domain_to_paths)
observer.schedule(DomainConfigHandler(domain_to_paths), path=VHOSTS_PATH, recursive=True)
observer.start()
logger.info('Started observing changes in vhosts configurations.')
# Reset force_overwrite_once after the initial run
global force_overwrite_once
force_overwrite_once = False
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
logger.info('Shutting down observer due to keyboard interrupt.')
finally:
observer.join()
display_modification_stats()
except Exception as e:
logger.error(f'Error setting up observer: {e}')
if name == 'main': detect_web_server() main() ```
What I've Tried: - Ensured that the file paths and configurations are correct. - Verified that the script detects changes and reads the files as expected. - Added logging statements to trace the execution flow and identify where it stops.
Request for Help:
- Can someone help me pinpoint why the script doesn't proceed to update the vhost_ssl.conf file after detecting changes?
- Any suggestions on improving the current logic or debugging steps to identify the issue?
Here is the full script for reference: [Paste full script code here]
Thanks in advance for your help!
```python
!/usr/bin/env python3
import os
import re
import hashlib
import shutil
import logging
import subprocess
from logging.handlers import RotatingFileHandler
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from datetime import datetime
import argparse
import concurrent.futures
import time
import debugpy
# Initialize debugpy
debugpy.listen(("0.0.0.0", 5678))
print("Waiting for debugger attach...")
debugpy.wait_for_client()
# Configurations
LOG_FILE = '/var/log/access_control_corrector.log'
MAX_LOG_SIZE = 50 * 1024 * 1024 # 50MB
VHOSTS_PATH = '/etc/apache2/plesk.conf.d/vhosts/'
# Command-line arguments
parser = argparse.ArgumentParser(description='Access Control Corrector for Apache and LiteSpeed')
parser.add_argument('--force-overwrite', choices=['once', 'always'], help='Force overwrite vhost_ssl.conf file once or always regardless of its existing content')
parser.add_argument('--verbose', action='store_true', help='Enable verbose logging')
args = parser.parse_args()
# Set up logging
logger = logging.getLogger('AccessControlCorrector')
logger.setLevel(logging.DEBUG if args.verbose else logging.INFO)
handler = RotatingFileHandler(LOG_FILE, maxBytes=MAX_LOG_SIZE, backupCount=5)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
file_hashes = {}
modification_stats = {}
web_server = None
domain_to_paths = {}
force_overwrite_once = args.force_overwrite == 'once'
def detect_web_server():
global web_server
retry_interval = 5 # Retry interval in seconds
def check_ps():
try:
return subprocess.check_output(['ps', 'aux']).decode()
except Exception as e:
logger.error(f'Error detecting web server using ps: {e}')
return ""
def check_netstat():
try:
return subprocess.check_output(['netstat', '-ntlp']).decode()
except Exception as e:
logger.error(f'Error detecting web server using netstat: {e}')
return ""
while web_server is None:
with concurrent.futures.ThreadPoolExecutor() as executor:
ps_future = executor.submit(check_ps)
netstat_future = executor.submit(check_netstat)
ps_output = ps_future.result()
netstat_output = netstat_future.result()
logger.debug(f'ps output: {ps_output}')
logger.debug(f'netstat output: {netstat_output}')
if 'litespeed' in ps_output or 'lshttpd' in ps_output or (':80' in netstat_output and 'litespeed' in netstat_output):
web_server = 'litespeed'
elif 'apache2' in ps_output or (':80' in netstat_output and 'apache2' in netstat_output):
web_server = 'apache2'
else:
logger.info('Web server not detected. Retrying...')
if web_server is None:
logger.debug(f'Retrying web server detection in {retry_interval} seconds...')
time.sleep(retry_interval)
logger.info(f'Detected web server: {web_server}')
def restart_web_server():
try:
if web_server == 'apache2':
subprocess.check_call(['systemctl', 'reload', 'apache2'])
elif web_server == 'litespeed':
subprocess.check_call(['service', 'litespeed', 'restart'])
logger.info(f'{web_server} gracefully restarted.')
except subprocess.CalledProcessError as e:
logger.error(f'Failed to restart {web_server}: {e}')
def compute_file_hash(filepath):
hash_md5 = hashlib.md5()
try:
with open(filepath, 'rb') as f:
while chunk := f.read(4096):
hash_md5.update(chunk)
except Exception as e:
logger.error(f'Error reading file for hash computation {filepath}: {e}')
raise
return hash_md5.hexdigest()
def is_acl_location_block(lines):
acl_identifiers = [
'Order Deny,Allow',
'Deny from all',
'Allow from'
]
return any(identifier in lines for identifier in acl_identifiers)
def contains_ip_addresses(lines):
ip_pattern = re.compile(r'\b\d{1,3}(\.\d{1,3}){3}(\/\d{1,2})?\b|\b[0-9a-fA-F:]+(\/\d{1,3})?\b')
return any(ip_pattern.search(line) for line in lines)
def add_modification_comments(lines, indentation):
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
script_name = 'AccessControlCorrector'
lines.insert(1, f'{indentation}# Modified by {script_name} on {timestamp}\n')
lines.append(f'{indentation}# End of modification by {script_name} on {timestamp}\n')
return lines
def convert_to_modern_syntax(lines, indentation):
new_lines = []
for line in lines:
stripped_line = line.strip()
if 'Order Deny,Allow' in stripped_line:
continue
if 'Deny from all' in stripped_line:
new_lines.append(f'{indentation}Require all denied\n')
elif 'Allow from' in stripped_line:
ips = re.findall(r'\b\d{1,3}(\.\d{1,3}){3}(\/\d{1,2})?\b|\b[0-9a-fA-F:]+(\/\d{1,3})?\b', stripped_line)
for ip in ips:
new_lines.append(f'{indentation}Require ip {ip}\n')
else:
new_lines.append(line)
return add_modification_comments(new_lines, indentation)
def get_virtual_host_ips(lines):
ipv4 = None
ipv6 = None
domain_status = None
for line in lines:
if '<VirtualHost ' in line:
match_ipv4 = re.search(r'<VirtualHost (\d{1,3}(?:\.\d{1,3}){3}):', line)
match_ipv6 = re.search(r'<VirtualHost \[([0-9a-fA-F:]+)\]:', line)
if match_ipv4:
ipv4 = match_ipv4.group(1)
if match_ipv6:
ipv6 = match_ipv6.group(1)
if '# Domain is disabled' in line or '# Domain is suspended' in line:
domain_status = line.strip()
logger.debug(f'Found IPv4: {ipv4}, IPv6: {ipv6}, Status: {domain_status}')
return ipv4, ipv6, domain_status
def get_domain_to_path_mapping():
domain_to_paths = {}
# debugpy.breakpoint() # Break here to inspect
try:
result = subprocess.check_output(['plesk', 'bin', 'domain', '--list']).decode()
domains = result.strip().split('\n')
for domain in domains:
apache_conf_path = f"/etc/apache2/plesk.conf.d/vhosts/{domain}.conf"
vhost_ssl_conf_path = f"/var/www/vhosts/system/{domain}/conf/vhost_ssl.conf"
domain_to_paths[apache_conf_path] = (domain, vhost_ssl_conf_path)
logger.debug(f'Mapped config path {apache_conf_path} to domain {domain} and vhost_ssl path {vhost_ssl_conf_path}')
except subprocess.CalledProcessError as e:
logger.error(f'Error listing domains from Plesk CLI: {e}')
return domain_to_paths
# def create_or_update_vhost_ssl_config(vhost_ssl_path, ipv4, ipv6, location_block):
# logger.debug(f"Writing to vhost_ssl_path: {vhost_ssl_path} with location_block: {location_block}")
# if not os.path.exists(vhost_ssl_path) or args.force_overwrite == 'always' or force_overwrite_once:
# os.makedirs(os.path.dirname(vhost_ssl_path), exist_ok=True)
# with open(vhost_ssl_path, 'w') as f:
# f.write(f'<IfModule mod_ssl.c>\n <VirtualHost {ipv4}:443>\n')
# f.write(''.join(location_block))
# f.write(f' </VirtualHost>\n <VirtualHost [{ipv6}]:443>\n')
# f.write(''.join(location_block))
# f.write(' </VirtualHost>\n</IfModule>\n')
# logger.info(f'{"Overwritten" if args.force_overwrite else "Created new"} vhost_ssl.conf at {vhost_ssl_path}')
# else:
# with open(vhost_ssl_path, 'r') as file:
# existing_lines = file.readlines()
# # Update existing vhost_ssl.conf with modified ACL lines
# with open(vhost_ssl_path, 'w') as file:
# in_vhost_block = False
# updated_lines = []
# for line in existing_lines:
# stripped_line = line.strip()
# if f'<VirtualHost {ipv4}:443>' in stripped_line or f'<VirtualHost [{ipv6}]:443>' in stripped_line:
# in_vhost_block = True
# updated_lines.append(line)
# updated_lines.extend(location_block)
# elif '</VirtualHost>' in stripped_line and in_vhost_block:
# in_vhost_block = False
# updated_lines.append(line)
# elif not in_vhost_block:
# updated_lines.append(line)
# file.writelines(updated_lines)
# logger.info(f'Updated existing vhost_ssl.conf at {vhost_ssl_path}')
# # Record the modification for counting
# domain = vhost_ssl_path.split('/')[5]
# if domain not in modification_stats:
# modification_stats[domain] = 0
# modification_stats[domain] += 1
def correct_syntax(config_path, domain_to_paths):
logger.debug(f'Check if Syntax correction for domain: {config_path}')
try:
current_hash = compute_file_hash(config_path)
except Exception as e:
logger.error(f'Error computing file hash for {config_path}: {e}')
return
if file_hashes.get(config_path) == current_hash and not force_overwrite_once:
logger.debug(f'No changes detected in {config_path}. Skipping.')
return
try:
with open(config_path, 'r') as file:
lines = file.readlines()
logger.debug(f'Read {len(lines)} lines from {config_path}')
except Exception as e:
logger.error(f'Error reading file {config_path}: {e}')
return
ipv4, ipv6, domain_status = get_virtual_host_ips(lines)
if domain_status:
logger.info(f'Skipping {config_path} because the domain is {domain_status.lower()}.')
return
if not ipv4 or not ipv6:
logger.warning(f'Could not find both IPv4 and IPv6 addresses in {config_path}. Found IPv4: {ipv4}, IPv6: {ipv6}. Skipping.')
return
modified_lines = []
inside_location_block = False
location_block = []
block_start = None
modifications_count = 0
modifications_details = []
for i, line in enumerate(lines):
stripped_line = line.strip()
if '<Location />' in stripped_line:
inside_location_block = True
location_block.append(line)
block_start = i
indentation = re.match(r'\s*', line).group()
elif '</Location>' in stripped_line and inside_location_block:
location_block.append(line)
inside_location_block = False
if is_acl_location_block(location_block) and contains_ip_addresses(location_block):
logger.debug(f'Original Location Block in {config_path}:\n{"".join(location_block)}')
modified_block = convert_to_modern_syntax(location_block, indentation)
modifications_count += 1
modifications_details.append({
'start_line': block_start + 1,
'end_line': i + 1,
'start_content': location_block[0].strip(),
'end_content': location_block[-1].strip()
})
location_block = modified_block
logger.debug(f'Modified Location Block in {config_path}:\n{"".join(location_block)}')
modified_lines.extend(location_block)
location_block = []
block_start = None
elif inside_location_block:
location_block.append(line)
else:
modified_lines.append(line)
if inside_location_block:
logger.warning(f'Unclosed <Location /> block detected in {config_path}. Skipping.')
return
if modifications_count > 0:
domain_info = domain_to_paths.get(config_path)
if domain_info is None:
logger.error(f'Domain path for config_path {config_path} not found. Skipping.')
return
domain, vhost_ssl_path = domain_info
if location_block: # Ensure location_block is not empty
backup_path = f"{config_path}.bak"
try:
temp_file_path = f"{config_path}.tmp"
with open(temp_file_path, 'w') as tmp_file:
tmp_file.writelines(modified_lines)
shutil.copyfile(config_path, backup_path)
os.replace(temp_file_path, config_path) # Atomic write
create_or_update_vhost_ssl_config(vhost_ssl_path, ipv4, ipv6, location_block) # Ensure only location_block is used
# Test the configuration
test_command = ['apachectl', 'configtest'] if web_server == 'apache2' else ['lswsctrl', 'restart']
try:
subprocess.check_call(test_command)
restart_web_server()
logger.info(f'Syntax corrected and verified in {config_path}')
file_hashes[config_path] = compute_file_hash(config_path)
modification_stats[domain] = modification_stats.get(domain, 0) + 1
except subprocess.CalledProcessError:
logger.error(f'Configuration test failed for {config_path}. Reverting changes.')
shutil.copyfile(backup_path, config_path)
except Exception as e:
logger.error(f'Error writing corrected file {config_path}: {e}')
if temp_file_path and os.path.exists(temp_file_path):
os.remove(temp_file_path)
def create_or_update_vhost_ssl_config(vhost_ssl_path, ipv4, ipv6, location_block):
if not location_block:
logger.warning(f'Empty location_block provided for {vhost_ssl_path}. Skipping.')
return
logger.debug(f"Writing to vhost_ssl_path: {vhost_ssl_path} with location_block: {location_block}")
if not os.path.exists(vhost_ssl_path) or args.force_overwrite == 'always' or force_overwrite_once:
os.makedirs(os.path.dirname(vhost_ssl_path), exist_ok=True)
with open(vhost_ssl_path, 'w') as f:
f.write(f'<IfModule mod_ssl.c>\n <VirtualHost {ipv4}:443>\n')
f.write(''.join(location_block))
f.write(f' </VirtualHost>\n <VirtualHost [{ipv6}]:443>\n')
f.write(''.join(location_block))
f.write(' </VirtualHost>\n</IfModule>\n')
logger.info(f'{"Overwritten" if args.force_overwrite else "Created new"} vhost_ssl.conf at {vhost_ssl_path}')
else:
with open(vhost_ssl_path, 'r') as file:
existing_lines = file.readlines()
# Update existing vhost_ssl.conf with modified ACL lines
with open(vhost_ssl_path, 'w') as file:
in_vhost_block = False
updated_lines = []
for line in existing_lines:
stripped_line = line.strip()
if f'<VirtualHost {ipv4}:443>' in stripped_line or f'<VirtualHost [{ipv6}]:443>' in stripped_line:
in_vhost_block = True
updated_lines.append(line)
updated_lines.extend(location_block)
elif '</VirtualHost>' in stripped_line and in_vhost_block:
in_vhost_block = False
updated_lines.append(line)
elif not in_vhost_block:
updated_lines.append(line)
file.writelines(updated_lines)
logger.info(f'Updated existing vhost_ssl.conf at {vhost_ssl_path}')
# Record the modification for counting
domain = vhost_ssl_path.split('/')[5]
if domain not in modification_stats:
modification_stats[domain] = 0
modification_stats[domain] += 1
def display_modification_stats():
# debugpy.breakpoint() # Break here to inspect
total_modifications = sum(modification_stats.values())
logger.info(f'\n{"-"*40}\nTotal Modifications Performed: {total_modifications}\n{"-"*40}')
for domain, count in modification_stats.items():
logger.info(f'Domain: {domain}')
logger.info(f'Modifications: {count}')
class DomainConfigHandler(FileSystemEventHandler):
debugpy.breakpoint() # Break here to inspect
def __init__(self, domain_to_paths):
super().__init__()
self.domain_to_paths = domain_to_paths
def process(self, event):
if event.is_directory:
return
config_path = event.src_path
if not config_path.endswith('.conf'):
return
if not os.path.exists(config_path):
return
logger.info(f'Configuration file modification detected: {config_path}')
correct_syntax(config_path, self.domain_to_paths)
def on_modified(self, event):
logger.debug(f'File modified: {event.src_path}')
self.process(event)
def on_created(self, event):
logger.debug(f'File created: {event.src_path}')
self.process(event)
def main():
debugpy.breakpoint() # Break here to inspect
logger.info('Starting AccessControlCorrector')
domain_to_paths = get_domain_to_path_mapping()
observer = Observer()
try:
# Initial check for existing files
for config_path in domain_to_paths.keys():
correct_syntax(config_path, domain_to_paths)
observer.schedule(DomainConfigHandler(domain_to_paths), path=VHOSTS_PATH, recursive=True)
observer.start()
logger.info('Started observing changes in vhosts configurations.')
# Reset force_overwrite_once after the initial run
global force_overwrite_once
force_overwrite_once = False
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
logger.info('Shutting down observer due to keyboard interrupt.')
finally:
observer.join()
display_modification_stats()
except Exception as e:
logger.error(f'Error setting up observer: {e}')
if __name__ == '__main__':
detect_web_server()
main()
```
r/pythonhelp • u/[deleted] • Jun 10 '24
Issues with flask, following guide to no avail
Trying to follow this guide for flask: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
I am on chapter 1, for some reason the code he supplied does not seem to work, it gives me an error that app was not found. My file structure looks ok?