Andrew Andrew - 3 months ago 12
Python Question

Python AttributeError: module 'runAnalytics' has no attribute 'run'

I am trying to grab an input from my main.py file using tkinter and then use that input in runAnalytics.py

main.py

import runAnalytics
import tkinter
import os
import centerWindow

loadApplication = tkinter.Tk()
loadApplication.title("Stock Analytics")
loadApplication.geometry("1080x720")

label1 = tkinter.Label(loadApplication, text = "Ticker")
input1 = tkinter.Entry(loadApplication)

loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = runAnalytics.run)

centerWindow.center(loadApplication)

loadAnalytics.pack()
label1.pack()
input1.pack()

loadApplication.mainloop()


runAnalytics.py

from yahoo_finance import Share
from main import input1
import tkinter
import os
import centerWindow


def run():
ticker = input1
loadAnalytics = tkinter.Tk()
loadAnalytics.title("$" + ticker + " Data")
loadAnalytics.geometry("1080x720")

print ("Price per share: " + ticker.get_price())

ticker.refresh()
print ("Price per share: " + ticker.get_price())

print("The dividend yield is: " + ticker.get_dividend_yield())

print("The 52 week low is: " + ticker.get_year_low())
print("The 52 week high is: " + ticker.get_year_high())
print("The volume is: " + ticker.get_volume())

print("The previous close was: " + ticker.get_prev_close())
print("The previous open was: " + ticker.get_open())

loadAnalytics.mainloop()


My error message reads as follows;

Traceback (most recent call last):
File "C:\Users\MyName\Documents\Python Projects\MarketData\main.py", line 1, in <module>
import runAnalytics
File "C:\Users\MyName\Documents\Python Projects\MarketData\runAnalytics.py", line 2, in <module>
from main import input1
File "C:\Users\MyName\Documents\Python Projects\MarketData\main.py", line 13, in <module>
loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = runAnalytics.run)
AttributeError: module 'runAnalytics' has no attribute 'run'

Answer

You have a circular import:

import runAnalytics
# ..
from main import input1

By the time main is being imported again, runAnalytics has not yet had a chance to execute the def run():.. section.

Resolve this by removing the from main import input1 line, and pass that object in as an argument instead:

def run(input1):

passing this in from the main.py module when you call the function:

loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = lambda: runAnalytics.run(input1))

Apart from the circular import, there is also the issue that whatever file you run as the main script in Python will be stored as the __main__ module. Importing that same script again will lead to a second module being created, now under the name main, and any objects created in that module are distinct from those in __main__.

Next, you'll want to remove the loadAnalytics.mainloop() call from run as you should not start a new mainloop from an already running loop. You probably also want to create a new TopLevel window instead of creating another Tk() root. You'd have to pass in loadApplication to run too if you go this way.