Kivy AttributeError: 'NoneType' object has no attribute 'ids'

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

ich bin dabei eine App mit kivy zu programmieren und bin auch schon relativ weit gekommen.

ich bin jetzt gerade dabei das nach einer gewissen zeit die daten automatisch neu abgefragt werden.

dafür habe ich einen thread gemacht der in einer while schleife alle 30 Sekunden die "on_start()" Funktion der kivy app abrufen soll

damit die abegerufenen daten angezeigt werden habe mit:

Code: Alles auswählen

self.root.ids.label.text=daten
die daten in ein label mit der id Label gesezt.

das hat bisher auch gut funktionirt aber als ich dann die Automatische Aktualisierung dazu gemacht habe:

Code: Alles auswählen

def AutoUpdateThread():
	_thread.start_new_thread(AutoUpdate, ())

def AutoUpdate():
	while True:
		TankstellenApp().on_start()
		time.sleep(30)
AutoUpdateThread()
bekomme ich immer diesen fehler:

Code: Alles auswählen

AttributeError: 'NoneType' object has no attribute 'ids'
kann mir vilicht irgendwer helfen? :?:
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

GUI-Anwendungen haben die Eigenart, bereits in einer while-Loop zu laufen. Ich würde an deiner Stelle keine Endlosschleife auf der GUI-Mainloop ausführen. Für das was du vorhast stellt Kivy Clock-Objekte zur Verfügung. https://kivy.org/doc/stable/api-kivy.clock.html

Damit kannst du sauberst einen Callback alle x-Sekunden aufrufen.
When we say computer, we mean the electronic computer.
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Leider kommt genau der selbe Fehler.
bringt also nichts
gibt es noch eine andere Möglichkeit?
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

MupfSpace hat geschrieben: Freitag 25. Januar 2019, 19:38 gibt es noch eine andere Möglichkeit?
Ja, du zeigst deinen vollständigen Code - ich kann jetzt nicht erraten was du versucht hast, und an welcher Stelle du Fehler gemacht haben könntest.
When we say computer, we mean the electronic computer.
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Okay ich habe schnell ein kleines Test Programm geschrieben:

Code: Alles auswählen


from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock

g=Builder.load_string("""
BoxLayout:
    Label:
	id:Label
	text:"test"
	 
	


""")

class myApp(App):
    def build(self):
        return g
    def on_start(self):
	data=self.root.ids.Label.text+"Test"
	self.root.ids.Labdl.text=data
	print("test")
		
Clock.schedule_interval(myApp().on_start(), 1)

myApp().run()
Error mit den ids:

Code: Alles auswählen

AttributeError: 'NoneType' object has no attribute 'ids'
Error ohne die ids(die 2 zeilen mit self.root.ids auskommentiert):

Code: Alles auswählen

 ValueError: callback must be a callable, got None
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MupfSpace: Mal ein paar Anmerkungen zum Quelltext: Das `_thread`-Modul gehört nicht zur öffentlichen API, wie man am führenden Unterstrich erkennen kann. Du kannst also nicht davon ausgehen, dass es das überhaupt gibt. Das ist also ein Fehler das zu verwenden. Für Threads ist das `threading`-Modul in der Standardbibliothek da.

Ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase) schreibt man Namen in Python klein_mit_unterstrichen. Das Du alles mögliche wie Klassen schreibst ist sehr verwirrend.

Es ist etwas komisch das Du `TankstellenApp()` aurufst. Was macht dieser Aufruf denn? Hoffentlich nicht jedes mal eine neue GUI-App erstellen, das wäre nämlich falsch. Du willst ja die Methode einer *bestehenden* App aufrufen. Und wenn `on_start()` eigentlich dazu da ist beim Start der Anwendung aufgerufen zu werden, dann sollte man das nicht danach noch mal oder gar mehrfach aufrufen, denn von der angedachten Semantik her können/dürfen da auch Sachen drin stehen, die nicht mehr als einmal ausgeführt werden sollen/dürfen.

Edit: Im abgeänderten Beispiel machst Du also den Fehler eine neu App zu erstellen statt die vorhandene zu verwenden. *Und* Du übergibst gar nicht die Methode sondern Du rufst die selbst sofort einmal auf und übergibst dann den *Rückgabewert*.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Ich habe jezt das alles nicht mehr im on_start() drin sondern in einer anderen funktion und es funktioniert immer noch nicht.

Was kann ich tun?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MupfSpace: Den oder die Fehler beseitigen?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Wenn ich wüsste Wie?
Weißt du Wie?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MupfSpace: Da niemand ausser Dir weiss wie Dein Code *jetzt* aussieht…

Allerdings hatte ich ja auch schon geschrieben was Du im bisher gezeigten falsch gemacht hast. Also: Keine neuen App-Objekte erstellen, sondern das vorhandene benutzen, und die *Methode* bei dem Aufruf von `Clock.schedule_interval()` übergeben und nicht deren *Rückgabewert*. Die Dokumentation von `Clock` ist hier im Thema ja schon verlinkt und da sind ja auch Beispiele drin wie man es macht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Wenn ich den Aufruf der Funktion ohne den klassen Namen in dem Fall der Name der app mache bekomme ich den Fehler das er die funktion nicht kennt...
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

MupfSpace hat geschrieben: Samstag 26. Januar 2019, 07:59 Wenn ich den Aufruf der Funktion ohne den klassen Namen in dem Fall der Name der app mache bekomme ich den Fehler das er die funktion nicht kennt...
Was zu erwarten ist, an dieser Stelle nicht richtig und auch gar nicht empfohlen wurde.

Wenn du myApp().on_start() aufrufst, passiert genau das. Es wird die Methode von myApp() aufgerufen, also "ausgeführt".

Wenn du hingegen myApp().on_start angibst, sagst du Python "ich meine diese Funktion", also du zeigst auf die Methode ohne sie wirklich aufzurufen und den Code im Methodenkörper auszuführen. Das soll der Scheduler tun, also passiert das automatisch durch Clock.

Bspw. aus der Doku:

Code: Alles auswählen

Clock.schedule_once(my_callback, 5)
Dort steht nirgendswo, dass du () hinter "my_callback" schreiben sollst.
When we say computer, we mean the electronic computer.
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Es passiert gar nichts

Code: Alles auswählen

Clock.schedule_interval(myApp().on_start,5)
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Wie sieht dein kompletter Code jetzt aus? Vielleicht kommst du uns etwas entgegen in dem wir dir nicht jeden Furz aus der Nase ziehen müssen.
When we say computer, we mean the electronic computer.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MupfSpace: Da passiert schon was, aber halt nicht in der App die Du siehst, sondern in der App die Du da noch mal erstellst, statt die vorhandene App zu verwenden. Nicht das ich das nicht schon mal geschrieben hätte…
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

@__blackjack__
Wieso sollte ich eine neue app erstellen und wo siehst du das?
@sls
Hier der Test code:

Code: Alles auswählen

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
g=Builder.load_string("""
BoxLayout:
	Label:
		id:Label
		text:"test"
	 
	


""")

class myApp(App):
	global r 
	r ="/"
	def build(self):
		return g
	def on.start(self):
		global r
		self.root.ids.Label.text=r
		print("test")
		r="^"
Clock.schedule_interval(myApp().on_start, 5)

myApp().run()



Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MupfSpace: Das sehe ich im Code. Der Aufruf ``myApp()`` erstellt ein neues App-Objekt und dieser Aufruf steht zweimal in Deinem Programm. Bei einem der beiden Objekte wird die `on_start()`-Methode regelmässig aufgerufen, aber es wird nicht als GUI angezeigt weil die `run()`-Methode nicht aufgerufen wird. Und das andere wird als GUI angezeigt, aber da wird natürlich die `on_start()`-Methode nicht regelmässig aufgerufen.

Wobei das nicht der Code ist, den Du tatsächlich laufen lässt, denn der enthält einen Syntaxfehler und kommt deshalb nicht am Compiler vorbei.

Zudem solltest Du ``global`` ganz schnell wieder vergessen. Das hat in einem ordentlichen Programm nichts zu suchen und schon gar nicht wenn man sowieso schon objektorientiert programmiert. Dann gibt es für ``global`` keine Ausrede.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

@sls
sls hat geschrieben: Samstag 26. Januar 2019, 12:34 Wie sieht dein kompletter Code jetzt aus?
die Clock funktion ist in zeile 854

Code: Alles auswählen

import os
import _thread
from plyer import notification
import time
import urllib.request
import urllib
from zipfile import ZipFile
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.settings import SettingsWithSidebar
from kivy.uix.screenmanager import Screen
from kivy.clock import Clock
import json

setting_json = json.dumps(
[
	{"type":"title",
	"title":"Automatische Preis-Aktualisierung"
	},
    {"type":"bool",
    "key":"AutoUpdate",
    "section":"settings"
    }



]





)

g=Builder.load_string("""
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import ListItemButton kivy.uix.listview.ListItemButton


<ListItemButton>:
	selected_color: 0,0,5,5
	deselected_color: 0,0,0,0
	size: (100, 175)
	on_press: app.versSelected(self)
ScreenManager:
	Screen
		name:'main'
		TabbedPanel:
			tab_width: 375
			pos: 0,-100
			do_default_tab: False
			TabbedPanelItem:
				text:"OMV-Neubiberg"
				BoxLayout:
					padding: 120
					orientation:"vertical"
					pos_hint:{'top':1}
					size_hint: None, None
					height: 775
					spacing: "100"
					BoxLayout:
						spacing:"300"
						orientation:"horizontal"
					BoxLayout:
						spacing:"300"
						orientation: "horizontal"
						Label:
							id: sorte1
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis1
							height: 15
							size_hint: None, None
							text:"Preis: "
					BoxLayout:
						orientation: "horizontal"
						spacing:"300"
						Label:
							id: sorte2
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis2
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte3
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis3
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte4
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis4
							size_hint: None, None
							height: 15
							text: "Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte5
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis5
							size_hint: None, None
							height: 15
							text:"Preis:"
			TabbedPanelItem:
				text:"DriversIn-Putzbrunn"
				BoxLayout:
					padding: 120
					orientation:"vertical"
					pos_hint:{'top':1}
					size_hint: None, None
					height: 775
					spacing: "100"
					BoxLayout:
						spacing:"300"
						orientation:"horizontal"
					BoxLayout:
						spacing:"300"
						orientation: "horizontal"
						Label:
							id: sorte1DVP
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis1DVP
							height: 15
							size_hint: None, None
							text:"Preis: "
					BoxLayout:
						orientation: "horizontal"
						spacing:"300"
						Label:
							id: sorte2DVP
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis2DVP
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte3DVP
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis3DVP
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte4DVP
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis4DVP
							size_hint: None, None
							height: 15
							text: "Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte5DVP
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis5DVP
							size_hint: None, None
							height: 15
							text:"Preis:"
			TabbedPanelItem:
				width:300
				text:"Shell-Kehferloh/Grasbrunn"
				BoxLayout:
					padding: 120
					orientation:"vertical"
					pos_hint:{'top':1}
					size_hint: None, None
					height: 775
					spacing: "100"
					BoxLayout:
						spacing:"300"
						orientation:"horizontal"
					BoxLayout:
						spacing:"300"
						orientation: "horizontal"
						Label:
							id: sorte1KGS
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis1KGS
							height: 15
							size_hint: None, None
							text:"Preis: "
					BoxLayout:
						orientation: "horizontal"
						spacing:"300"
						Label:
							id: sorte2KGS
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis2KGS
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte3KGS
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis3KGS
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte4KGS
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis4KGS
							size_hint: None, None
							height: 15
							text: "Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte5KGS
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis5KGS
							size_hint: None, None
							height: 15
							text:"Preis:"
					BoxLayout:
						orientation:"horizontal"
						spacing:"300"
						Label:
							id: sorte6KGS
							size_hint: None, None
							height: 15
							text:"Benzinsorte:"
						Label:
							id: preis6KGS
							size_hint: None, None
							height: 15
							text:"Preis:"
				
            
        BoxLayout:
            padding: 350
            Button:
                id: refBUT
                background_color: 0,0,0,0
                size_hint: None, None
                height: 100
                width: 100
                on_press: app.on_start()
                on_release: app.on_start()
                Image:
                    source: "C.png"
                    y: self.parent.y + self.parent.height - 100
                    x: self.parent.x
                    size: 100, 100
                    allow_stretch: True
                
                    
                

		ActionBar:
			id: UpdInf
			background_color: 5,5,5,5
			pos_hint:{'bottom':1}
			ActionView:
				id: UpdInfView
				use_separator: True
				ActionPrevious:
					app_icon: "Cl.png"
					with_previous: False
					title:"Update verfuegbar"
					on_press: app.UpdInf_gone(self)
				ActionButton:
					icon:"Dow.png"
		ActionBar:
		    pos_hint: {'top':1}
		    ActionView:
		        use_separator: True
		        ActionPrevious:
		            title: 'Tankstellen App'
		            with_previous: False
		            #app_icon: 'Transparent.png'
		        ActionButton:
		        	#icon:'C.png'
		        ActionButton:
		            text: 'Einstellugen'
		            on_press: root.current='settings'
		        ActionButton:
		            text: 'Navigation'
		            on_press: root.current='NAV'
		        ActionButton:
		            text: 'Versionen'
		            on_press: root.current='Versions'
		        ActionGroup:
		            text: 'Hilfe'
		            ActionButton:
		                text: 'Anleitung'
		                on_press: root.current='guide'
		            ActionButton:
		                text: 'Quickstart'
		                on_press: root.current='QUICKSTART-Main'
		            ActionButton:
		        	    text: 'Support'
		        	    on_press: root.current='SUPPORT'
		        	    
	Screen:
		name:'settings'
		BoxLayout:
			orientaation:"vertical"
			BoxLayout:
				Label:
					text:"   Benachrichtigung erhalten\\n   bei guenstigem Preis"
				Switch:
					id:CheapNotSwitch
					on_active: app.CheapNotSwitched(self, self.active)
					on_active: app.open_settings()
					
					
#		BoxLayout:
#			orientation:"vertical"
#			Label:
#				text_size: self.size
#				halign: 'center'
#				valign: 'middle'
#				font_size: dp(25)
#				text:"Noch nicht verfuegbar\\nwarte auf Updates und versuche es dann erneut"
#			Button:
#				size_hint: None, None
#				height: 125
#				width: 750
#				text:"Auf Updates pruefen"
#				on_press: root.current='Versions'
		ActionBar:
			pos_hint:{'top':1}
			ActionView:
				use_seperator: True
				ActionPrevious:
					title:"Einstellungen"
					with_previous: True
					app_icon:'S.png'
					on_press: root.current='main'
				
	Screen:
		name:'NAV'
		BoxLayout:
			orientation:"vertical"
			Label:
				text_size: self.size
				halign: 'center'
				valign: 'middle'
				font_size: dp(25)
				text:"Noch nicht verfuegbar\\nwarte auf Updates und versuche es dann erneut"
			Button:
				size_hint: None, None
				height: 125
				width: 750
				text:"Auf Updates pruefen"
				on_press: root.current='Versions'
		ActionBar:
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					title:"Navigation"
					with_previous: True
					app_icon:'N.png'
					on_press: root.current='main'
					
	Screen:
		name:"SUPPORT"
		BoxLayout:
			orientation:"vertical"
			Label:
				text_size: self.size
				halign: 'center'
				valign: 'middle'
				font_size: dp(25)
				text:"Noch nicht verfuegbar\\nwarte auf Updates und versuche es dann erneut"
			Button:
				size_hint: None, None
				height: 125
				width: 750
				text:"Auf Updates pruefen"
				on_press: root.current='Versions'
		ActionBar:
			pos_hint:{'top':1}
			ActionView:
				use_seperator: True
				ActionPrevious:
					title:"Support"
					with_previous: True
					app_icon:"Su.png"
					on_press: root.current="main"
	Screen:
		name:"Versions"
		BoxLayout:
			orientation:"vertical"
			Label:
				size_hint: None, None
				pos_hint:{'top':1}
				text:""
			BoxLayout:
				orientation:"horizontal"
				Button:
					text:"Info"
				Button:
					text:"Instalieren"
			ListView:
				adapter: ListAdapter(data=['foo', 'bar', 'baz'], cls=ListItemButton)
				size_hint: None, None
				width: 725
				height: 1100
		ActionBar:
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					title:"Versionen"
					app_icon:"V.png"
					with_previous: True
					on_press: root.current='main'
					
	Screen:
		name:"guide"
		BoxLayout:
			orientation:"vertical"
			Label:
				text_size: self.size
				halign: 'center'
				valign: 'middle'
				font_size: dp(25)
				text:"Noch nicht verfuegbar\\nwarte auf Updates und versuche es dann erneut"
			Button:
				size_hint: None, None
				height: 125
				width: 750
				text:"Auf Updates pruefen"
				on_press: root.current='Versions'
		ActionBar:
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					title:"Anleitung"
					app_icon:"I.png"
					with_previous: True
					on_press: root.current='main'
					
	Screen:
		name:'QUICKSTART-Main'
		BoxLayout:
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					app_icon:"Transparent.png"
					with_previous: False
				ActionButton:
					icon:"Cl.png"	
					on_press: root.current='main'
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'Bottom':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					with_previous: False
					app_icon:"NBa.png"
					ActionButton:
						icon:"Cg.gif"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Ne.png"
						on_press: root.current='QUICKSTART-s2'
	Screen:
		name:'QUICKSTART-s2'
		BoxLayout:
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					app_icon:"Transparent.png"
					with_previous: False
				ActionButton:
					icon:"Cl.png"	
					on_press: root.current='main'
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'Bottom':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					with_previous: False
					app_icon:"Ba.png"
					on_press: root.current='QUICKSTART-Main'
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cg.gif"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Ne.png"
						on_press: root.current='QUICKSTART-s3'
	Screen:
		name:'QUICKSTART-s3'
		BoxLayout:
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					app_icon:"Transparent.png"
					with_previous: False
				ActionButton:
					icon:"Cl.png"	
					on_press: root.current='main'
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'Bottom':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					with_previous: False
					app_icon:"Ba.png"
					on_press: root.current='QUICKSTART-s2'
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cg.gif"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Ne.png"
						on_press: root.current="QUICKSTART-s4"
	Screen:
		name:'QUICKSTART-s4'
		BoxLayout:
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					app_icon:"Transparent.png"
					with_previous: False
				ActionButton:
					icon:"Cl.png"	
					on_press: root.current='main'
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'Bottom':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					with_previous: False
					app_icon:"Ba.png"
					on_press: root.current='QUICKSTART-s3'
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cg.gif"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Ne.png"
						on_press: root.current="QUICKSTART-s5"

	Screen:
		name:'QUICKSTART-s5'
		BoxLayout:
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'top':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					app_icon:"Transparent.png"
					with_previous: False
				ActionButton:
					icon:"Cl.png"	
					on_press: root.current='main'
		ActionBar:
			background_color: 0,0,0,0
			pos_hint:{'Bottom':1}
			ActionView:
				use_separator: True
				ActionPrevious:
					with_previous: False
					app_icon:"Ba.png"
					on_press: root.current='QUICKSTART-s4'
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cw.png"
					ActionButton:
						icon:"Cg.gif"
					ActionButton:
						icon:"NNe.png"
	    	
""")


class TankstellenApp(App):
    global c
    c = 1
    def CheapNotSwitched(self, instance, value):
        if value == True:
        	notification.notify(message="Du erhälst ab jezt Benachrichtigungem bei günstigem Preis!\nDu kannst in den Einstellungen die Preise verändern bei denen du Benachrichtigugen erhalten willst!")
	        CheapNotify=open("/storage/emulated/0/TankstellenApp/CheapNotify.val", "w")
	        CheapNotify.write("True")
	        CheapNotify.close()
        else:
	        CheapNotify=open("/storage/emulated/0/TankstellenApp/CheapNotify.val", "w")
	        CheapNotify.write("Fasle")
	        CheapNotify.close()
            	
    def on_start(self):
        global c
        if c == 1:
            self.root.ids.refBUT.background_color=0,0,0,0
            c = 0
        else:
            self.root.ids.refBUT.background_color=0,0,9,9
            c = 1
        if os.path.exists("/storage/emulated/0/TankstellenApp") == True:
            pass
        else:
            urllib.request.urlretrieve("http://mscpiserver/TankstellenApp/Appfiles/files.zip", "/storage/emulated/0/files.zip")
            ZipFile('/storage/emulated/0/files.zip').extractall("/storage/emulated/0/")
            os.remove("/storage/emulated/0/files.zip")
        
        global UpdateDA

        checkVers=urllib.request.urlopen("http://mscpiserver/TankstellenApp/Versionen/latest.vers").read()
        currentVers=open("/storage/emulated/0/TankstellenApp/vers.","r").read()
        checkVers=str(checkVers)
        currentVers=str(currentVers)
        print(checkVers)
        print(currentVers)
        if checkVers.replace("b'","").replace("'","")==currentVers:
            UpdateDA = False
        else:
            UpdateDA = True
                       
        
        if UpdateDA==True:
            self.root.ids.UpdInf.pos_hint={'bottom':1}
        else:
            self.root.ids.UpdInf.pos_hint={'top':1}

        getPrices=urllib.request.urlopen("http://mscpiserver/TankstellenApp/PreisErmitlung/OMVNBB.pri")
        #getPrices=open("PreisErmitlung/OMVNBB.pri","r")
        getPrices=str(getPrices.read())
        getPrices=getPrices.split(";")
        print(getPrices)
        n = 0
        for preis in getPrices:
            n = n+1
            if n == 1:
                self.root.ids.sorte1.text=preis.replace("b'", "")
            if n == 2:
                self.root.ids.preis1.text=preis
            if n == 3:
                self.root.ids.sorte2.text=preis
            if n == 4:
                self.root.ids.preis2.text=preis
            if n == 5:
                self.root.ids.sorte3.text=preis
            if n == 6:
                self.root.ids.preis3.text=preis
            if n == 7:
                self.root.ids.sorte4.text=preis
            if n == 8:
                self.root.ids.preis4.text=preis
            if n == 9:
                self.root.ids.sorte5.text=preis
            if n == 10:
                self.root.ids.preis5.text=preis.replace("'", "")
                break

        #getPricesDVP=open("PreisErmitlung/DRIVERSINPB.pri","r")
        getPricesDVP=urllib.request.urlopen("http://mscpiserver/TankstellenApp/PreisErmitlung/DRIVERSINPB.pri")
        getPricesDVP=getPricesDVP.read()
        getPricesDVP=str(getPricesDVP).split(";")
        print(getPricesDVP)
        n = 0
        for preis in getPricesDVP:
            n = n+1
            if n == 1:
                self.root.ids.sorte1DVP.text=preis.replace("b'", "")
            if n == 2:
                self.root.ids.preis1DVP.text=preis
            if n == 3:
                self.root.ids.sorte2DVP.text=preis
            if n == 4:
                self.root.ids.preis2DVP.text=preis
            if n == 5:
                self.root.ids.sorte3DVP.text=preis
            if n == 6:
                self.root.ids.preis3DVP.text=preis
            if n == 7:
                self.root.ids.sorte4DVP.text=preis
            if n == 8:
                self.root.ids.preis4DVP.text=preis
            if n == 9:
                self.root.ids.sorte5DVP.text=preis
            if n == 10:
                self.root.ids.preis5DVP.text=preis.replace("'", "")
                break

        #getPricesKGS=open("PreisErmitlung/SHELLKGB.pri","r")
        getPricesKGS=urllib.request.urlopen("http://mscpiserver/TankstellenApp/PreisErmitlung/SHELLKGB.pri")
        getPricesKGS=getPricesKGS.read()
        getPricesKGS=str(getPricesKGS).split(";")
        print(getPricesKGS)
        n = 0
        for preis in getPricesKGS:
            n = n+1
            if n == 1:
                self.root.ids.sorte1KGS.text=preis.replace("b'", "")
            if n == 2:
                self.root.ids.preis1KGS.text=preis
            if n == 3:
                self.root.ids.sorte2KGS.text=preis
            if n == 4:
                self.root.ids.preis2KGS.text=preis
            if n == 5:
                self.root.ids.sorte3KGS.text=preis
            if n == 6:
                self.root.ids.preis3KGS.text=preis
            if n == 7:
                self.root.ids.sorte4KGS.text=preis
            if n == 8:
                self.root.ids.preis4KGS.text=preis
            if n == 9:
                self.root.ids.sorte5KGS.text=preis
            if n == 10:
                self.root.ids.preis5KGS.text=preis
            if n == 11:
                self.root.ids.sorte6KGS.text=preis
            if n == 12:
                self.root.ids.preis6KGS.text=preis.replace("'", "")
                break
		
        CheapNotify=open("/storage/emulated/0/TankstellenApp/CheapNotify.val", "r")
        CheapNotify=CheapNotify.read()
        if CheapNotify == "True":
            pass
        
	
	   
		
		
    def UpdInf_gone(self, ActionPrevious):
        self.root.ids.UpdInf.pos_hint={'top':1}
    def versSelected(self, ListItemButton):
        print("^")
    def build(self):
	    self.settings_cls = SettingsWithSidebar
	    self.use_kivy_settings= False
	    return g
    def build_config(self, config):
        self.config.setdefaults('settings',{"AutoUpdate": True})
    def build_settings(self,settings):
	    settings.add_json_panel('Einstellungen', self.config, data=setting_json)

    Clock.schedule_interval(on_start, 30)

   
# def AutoUpdateThread():
# 	_thread.start_new_thread(AutoUpdate, ())

# def AutoUpdate():
# 	while True:
# 		TankstellenApp().on_start()
# 		time.sleep(1)
# AutoUpdateThread()



#GAS=TankstellenApp()
#GAS.run()
print("run0")
TankstellenApp().run()

Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@MupfSpace: Der Unterstrich bei _thread sagt, dass dieses Modul nicht zur direkten Benutzung gedacht ist.
Vergiß, dass es »global« gibt. Zum Teil ist die Benutzung auch unsinnig. Die Klasse TankstellenApp hat keine __init__-Methode, in der die ganzen globalen Variablen als Attribute angelegt werden sollten. /storage/emulated/0/TankstellenApp/CheapNotify.val, /storage/emulated/0/TankstellenApp und /storage/emulated/0 kommen mehrfach im Code vor und sollten als Konstanten irgendwo am Anfang der Datei definiert werden.
Dateien öffnet man innerhalb eines with-Statements. Willst Du wirklich »Fasle« in eine Datei schreiben?
Die Einrückung ist uneinheitlich und sollte immer 4 Leerzeichen pro Ebene sein.
Explizite Vergleiche auf == True sind überflüssig, weil beim Vergleich nur wieder ein Wahrheitswert als Ergebnis herauskommt.
Vermeide Abkürzungen und halte dich an die Namenskonvention, dass Variablen klein_mit_unterstrich geschrieben werden.
Dateien und URLs die man öffnet sollte man auch wieder schließen. Du willst nicht mit der Stringrepräsentation eines Bytes-Objekt arbeiten und dessen b' ersetzen, sondern die Bytes per decode in einen String umwandeln. Statt url.request wäre das Modul requests bequemer.
getPrices ist eher ein Name für eine Funktion als für eine Variable. Die for-Schleife enthält sehr viel kopierten Code und wieder replace.
schedule_interval auf der Funktion aufzurufen ist genauso falsch, Du mußt es als Methode auf der tatsächlichen app-Instanz aufrufen.

Code: Alles auswählen

from io import BytesIO
from zipfile import ZipFile
import urllib.request

STORAGE = "/storage/emulated/0"
APP_PATH = os.path.join(STORAGE, "TankstellenApp")
URL = "http://mscpiserver/TankstellenApp"

class TankstellenApp(App):
    def __init__(self):
        self.blink = True
        self.update = False

    def cheap_not_switched(self, instance, value):
        if value:
        	notification.notify(message="Du erhälst ab jetzt Benachrichtigungem bei günstigem Preis!\n"
                "Du kannst in den Einstellungen die Preise verändern bei denen du Benachrichtigugen erhalten willst!")
	    with open(os.path.join(APP_PATH, "CheapNotify.val", "w") as output:
            output.write(str(value))
    
    @staticmethod
    def download_files():
        if not os.path.exists(APP_PATH):
            with urllib.request.urlopen(URL + "/Appfiles/files.zip") as response:
                data = BytesIO(response.read())
            with ZipFile(data) as files:
                files.extractall(STORAGE)

    def check_version(self):
        with urllib.request.urlopen(URL + "/Versionen/latest.vers") as response:
            version = request.read().decode(request.headers.get_content_charset() or "ASCII")
        with open(os.path.join(APP_PATH, "vers")) as data:
            current_version = data.read()
        self.update = version != current_version

    def update_prices(url, labels):
        with urllib.request.urlopen(URL + "/Versionen/latest.vers") as response:
            prices = request.read().decode(request.headers.get_content_charset() or "ASCII")
        for label, price in zip(label, prices.split(';')):
            label.text = price

    def on_start(self):
        self.root.ids.refBUT.background_color=(0,0,0,0) if self.blink else (0,0,9,9)
        self.blink = not self.blink
        self.download_files()
        self.check_version()
        self.root.ids.UpdInf.pos_hint = {'bottom' if self.update else 'top': 1}
        ids = self.root.ids
        self.update_prices("/PreisErmitlung/OMVNBB.pri", [
            ids.sorte1, ids.preis1,
            ids.sorte2, ids.preis2,
            ids.sorte3, ids.preis3,
            ids.sorte4, ids.preis4,
            ids.sorte5, ids.preis5,
        ])
        self.update_prices("/PreisErmitlung/DRIVERSINPB.pri", [
            ids.sorte1DVP, ids.preis1DVP,
            ids.sorte2DVP, ids.preis2DVP,
            ids.sorte3DVP, ids.preis3DVP,
            ids.sorte4DVP, ids.preis4DVP,
            ids.sorte5DVP, ids.preis5DVP,
        ])
        self.update_prices("/PreisErmitlung/SHELLKGB.pri", [
            ids.sorte1KGS, ids.preis1KGS,
            ids.sorte2KGS, ids.preis2KGS,
            ids.sorte3KGS, ids.preis3KGS,
            ids.sorte4KGS, ids.preis4KGS,
            ids.sorte5KGS, ids.preis5KGS,
            ids.sorte6KGS, ids.preis6KGS,
        ])

def main():
    app = TankstellenApp()
    Clock.schedule_interval(app.on_start, 30)
    app.run()

if __name__ == '__main__':
    main()
MupfSpace
User
Beiträge: 169
Registriert: Montag 25. Dezember 2017, 20:26

Danke.
ich habe mir den Code von dir angesehen und übernommen.
bekomme allerdings einen Fehler zu dem ich auch nichts im Internet gefunden habe.

Code: Alles auswählen

Traceback (most recent call last):
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\ptvsd_launcher.py", line 45, in <module>
     main(ptvsdArgs)
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\__main__.py", line 265, in main
     wait=args.wait)
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\__main__.py", line 256, in handle_args
     run_main(addr, name, kind, *extra, **kwargs)
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 52, in run_main
     runner(addr, name, kind == 'module', *extra, **kwargs)
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\runner.py", line 32, in run
     set_trace=False)
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1283, in run
     return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1290, in _exec
     pydev_imports.execfile(file, globals, locals)  # execute the script
   File "c:\Users\MupfSpace\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
     exec(compile(contents+"\n", file, 'exec'), glob, loc)
   File "c:\Users\MupfSpace\Desktop\App test1\mainpy3v5.0.py", line 789, in <module>
     main()
   File "c:\Users\MupfSpace\Desktop\App test1\mainpy3v5.0.py", line 786, in main
     app.run()

Code: Alles auswählen

 AttributeError: 'TankstellenApp' object has no attribute 'built'
Antworten