Andrew Andrew - 3 months ago 10
Python Question

Python AttributeError: 'str' object has no attribute 'get_price'

I am trying to take user input from main.py and then tailor the output to said user input. Not only am I getting this error but it seems the my runAnalytics is running when I start main.py, not when I hit my button command to do so.

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(input1))

centerWindow.center(loadApplication)

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

loadApplication.mainloop()


runAnalytics.py

from yahoo_finance import Share
import tkinter
import os
import centerWindow

def run(input1):
ticker = Share(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()


Error message:


Traceback (most recent call last):
File "C:\Users\MyName\Documents\Python Projects\MarketData\main.py", line 13, in
loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = runAnalytics.run(input1))
File "C:\Users\MyName\Documents\Python Projects\MarketData\runAnalytics.py", line 12, in run
print ("Price per share: " + ticker.get_price())
AttributeError: 'str' object has no attribute 'get_price'

Answer

Your assumption that runAnalytics is running is correct since the function is executed when binding it to the button the way you did.

According to the effbot docs you need to use a lambda function in order to bind a function with passed arguments to a button like this:

import tkinter

def test_func(val):
    print(type(val))
    print(val)
    share_id = val.get()
    print(share_id)


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=lambda: test_func(input1))


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

loadApplication.mainloop()

However, there is a second thing to keep in mind:

input1 = tkinter.Entry(loadApplication)

creates an Entry widget called input1 which is then passed to the function. The thing is that input1 does not contain the string you typed into the entry widget but a reference to the widget (widget ID). In order to get the widget's content you need to call its .get() method as shown in my code snippet.

Comments