Python2 co jest nie tak z tym językiem


(arekk-99) #1

Witam bardzo serdecznie.
Ja nie wiem, czy ja jestem jakiś niepojętny, czy Python tak ma, ze wali błędami tam, gdzie ich wcześniej nie było?
Zmieniłem kawałek kodu w aplikacji do Twittera, żeby pobierał długie tweety z twishorta. Przestało działać coś kilkanaście linii wyżej. Usunąłem tamto, dalej nie działaóło. Miałem dzialjacą kobię kodu w innym folderze. Uruchomiłem ją i wszystko działało. Podmieniłem tne1 plik, gdzie się coś tam nei zgadza i dalej się to nie zgadza.
Ludzie, czy to Python jest taki bezsensowny, żę na jednej wersji kodu w innym folderze wszystko działa, a gdy podmienię ten plik, który nie działa z tego folderu, co działa do tego folderu, co nie działa to on nadal nei chce działać, a na innej kopii wszystko śmiga.
Ludzie, o co tu chodzi? Nie wklejam kodu, bo to ejst bez sensu. wiele razy się tak działo w wielu różnych miejscach…


(pocolog) #2

Jeśli kod piszesz tak jak posty, to cóż… nie wiadomo dlaczego nie działa :laughing:


(iJuliusz) #3

Możesz mieć rację.
Nieraz szukałem buga w kodzie Pythona, a okazywała się literówka w zmiennej.

BTW. Python2 i Python3 różnią się w kodowaniu


(arekk-99) #4

To nie mój kod. forkuję sobie z githuba.
Czepiacie się.
Chyba nie umiem umieszczać kodu, bo znowu wcięcia pogubił.

-- coding: utf-8 --

import timestring
import datetime
import time
import twitter
import re
import config
url_re = re.compile(r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|(([^\s()<>]+|(([^\s()<>]+)))))+(?:(([^\s()<>]+|(([^\s()<>]+))))|[^\s`!()[]{};:’".,<>?]))")
url_re2 = re.compile("(?:\w+://|www.)[^ ,.?!#%=+][^ ]*")
bad_chars = “’\.,{}:;”"
import gui
class buffer(object):
def init(self,name,statuses):
self.name=name
self.statuses=statuses
self.position=0

global buffers
buffers=[]

def get_buffer_item(name,index):
for i in range(len(buffers)):
if buffers[i].name==name:
return buffers[i].statuses[index]

def add_buffer_item(name,item):
for i in range(len(buffers)):
if buffers[i].name==name:
buffers[i].statuses.insert(0,item)
if gui.interface.window.focused==name:
gui.interface.window.tweets.Insert(process_tweet(item),0)

def insert_buffer_items(name):
gui.interface.window.tweets.Clear()
for i in range(len(buffers)):
if buffers[i].name==name:
for i2 in range(len(buffers[i].statuses)):
gui.interface.window.tweets.Insert(process_tweet(buffers[i].statuses[i2]),gui.interface.window.tweets.GetCount())
gui.interface.window.tweets.SetSelection(buffers[i].position)

def process_tweet(s,return_only_text=False):
text=s[‘text’]
if s.has_key(“entities”)!=False:
if s[‘entities’].has_key(“urls”)!=False:
urls=find_urls_in_text(text)
for url in range(0,len(urls)):
try:
text=text.replace(urls[url],s[‘entities’][‘urls’][url][‘expanded_url’])
except IndexError:
pass

if s.has_key("retweeted_status")!=False:

	qs=s['retweeted_status']
	text="Retweeting "+qs['user']['name']+" ("+qs['user']['screen_name']+": "+process_tweet(qs,True)

if s.has_key("quoted_status")!=False:

	qs=s['quoted_status']
	urls=find_urls_in_text(text)
	for url in range(0,len(urls)):
		if qs['user']['screen_name'] in urls[url]:

			text=text.replace(urls[url],"Quoting "+qs['user']['name']+": "+process_tweet(qs,True))

s['text']=text
if return_only_text==False:
	return template_to_string(s)
else:
	return text

def find_urls_in_text(text):
return [s.strip(bad_chars) for s in url_re2.findall(text)]

def template_to_string(s):
if s.has_key(“sender”):
template=config.appconfig[‘general’][‘message_template’]
else:
template=config.appconfig[‘general’][‘tweet_template’]

s['created_at']=parse_date(s['created_at'])
temp=template.split(" ")
for i in range(len(temp)):
	if "$" in temp[i]:
		t=temp[i].split("$")
		r=t[1]
		if "." in r:
			q=r.split(".")
			o=q[0]
			p=q[1]

			if s.has_key(o) and s[o].has_key(p):
				try:
					template=template.replace("$"+t[1]+"$",s[o][p])
				except:
					pass

		else:
			if s.has_key(t[1]):
				try:
					template=template.replace("$"+t[1]+"$",s[t[1]])
				except:
					pass
return template

def get_users_in_tweet(s):
new=""

if s.has_key("quoted_status")!=False:
	s['text']+=" "+s['quoted_status']['user']['screen_name']

if s.has_key("retweeted_status")!=False:
	s['text']+=" "+s['retweeted_status']['user']['screen_name']

new="@"+s['user']['screen_name']

weew=s['text'].split(" ")
for i in range(0,len(weew)):
	if "@" in weew[i] and weew[i]!="@"+twitter.screenname:
		new+=" "+weew[i]
return new

def user(s):
if s.has_key(‘user’):
return s[‘user’][‘screen_name’]
else:
return s[‘sender’][‘screen_name’]

def get_focused_tweet():
index=gui.interface.window.tweets.GetSelection()
focused=gui.interface.window.focused
return get_buffer_item(focused,index)

def parse_date(date):
try:
ti=datetime.datetime.now()
tz=time.altzone
date2=datetime.datetime.strptime(date.replace("+0000 “,”"),"%a %b %d %H:%M:%S %Y")
try:
date2+=datetime.timedelta(seconds=0-tz)
except:
pass
returnstring=""

	try:
		if date2.year==ti.year:
			if date2.day==ti.day and date2.month==ti.month:
				returnstring=""
			else:
				returnstring=date2.strftime("%m/%d/%Y, ")
		else:
			returnstring=date2.strftime("%m/%d/%Y, ")

		if returnstring!="":
			returnstring+=date2.strftime("%I:%M:%S %p")
		else:
			returnstring=date2.strftime("%I:%M:%S %p")
	except:
		pass
except:
	return date
return returnstring

def update_buffer_item(name,index,item):
remove_buffer_item(name,index)
insert_buffer_item(name,index,item)

def remove_buffer_item(name,index):
for i in range(len(buffers)):
if buffers[i].name==name:
buffers[i].statuses.pop(index)
if gui.interface.window.focused==name:
gui.interface.window.tweets.Delete(index)

def insert_buffer_item(name,index,item):
for i in range(len(buffers)):
if buffers[i].name==name:
buffers[i].statuses.insert(index,item)
if gui.interface.window.focused==name:
gui.interface.window.tweets.Insert(process_tweet(item),index)


(krystian3w) #5

To nie mój kod. forkuję sobie z githuba.

może oryginał ma instrukcje kompilacji


Chyba nie umiem umieszczać kodu, bo znowu wcięcia pogubił.

Zaczynasz od ``` enter, wklejasz kod, enter i kończysz ``` i masz efekt (jak kolorowanie składni nie działa można wymusić pythona - o tym na końcu):

# -*- coding: utf-8 -*-
import timestring
import datetime
import time
import twitter
import re
import config
url_re = re.compile(r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?]))")
url_re2 = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
bad_chars = "'\\.,[](){}:;\""
import gui
class buffer(object):
	def __init__(self,name,statuses):
		self.name=name
		self.statuses=statuses
		self.position=0

global buffers
buffers=[]

def get_buffer_item(name,index):
	for i in range(len(buffers)):
		if buffers[i].name==name:
			return buffers[i].statuses[index]

def add_buffer_item(name,item):
	for i in range(len(buffers)):
		if buffers[i].name==name:
			buffers[i].statuses.insert(0,item)
			if gui.interface.window.focused==name:
				gui.interface.window.tweets.Insert(process_tweet(item),0)

def insert_buffer_items(name):
	gui.interface.window.tweets.Clear()
	for i in range(len(buffers)):
		if buffers[i].name==name:
			for i2 in range(len(buffers[i].statuses)):
				gui.interface.window.tweets.Insert(process_tweet(buffers[i].statuses[i2]),gui.interface.window.tweets.GetCount())
			gui.interface.window.tweets.SetSelection(buffers[i].position)

def process_tweet(s,return_only_text=False):
	text=s['text']
	if s.has_key("entities")!=False:
		if s['entities'].has_key("urls")!=False:
			urls=find_urls_in_text(text)
			for url in range(0,len(urls)):
				try:
					text=text.replace(urls[url],s['entities']['urls'][url]['expanded_url'])
				except IndexError:
					pass

	if s.has_key("retweeted_status")!=False:

		qs=s['retweeted_status']
		text="Retweeting "+qs['user']['name']+" ("+qs['user']['screen_name']+": "+process_tweet(qs,True)

	if s.has_key("quoted_status")!=False:

		qs=s['quoted_status']
		urls=find_urls_in_text(text)
		for url in range(0,len(urls)):
			if qs['user']['screen_name'] in urls[url]:

				text=text.replace(urls[url],"Quoting "+qs['user']['name']+": "+process_tweet(qs,True))

	s['text']=text
	if return_only_text==False:
		return template_to_string(s)
	else:
		return text

def find_urls_in_text(text):
	return [s.strip(bad_chars) for s in url_re2.findall(text)]

def template_to_string(s):
	if s.has_key("sender"):
		template=config.appconfig['general']['message_template']
	else:
		template=config.appconfig['general']['tweet_template']

	s['created_at']=parse_date(s['created_at'])
	temp=template.split(" ")
	for i in range(len(temp)):
		if "$" in temp[i]:
			t=temp[i].split("$")
			r=t[1]
			if "." in r:
				q=r.split(".")
				o=q[0]
				p=q[1]

				if s.has_key(o) and s[o].has_key(p):
					try:
						template=template.replace("$"+t[1]+"$",s[o][p])
					except:
						pass

			else:
				if s.has_key(t[1]):
					try:
						template=template.replace("$"+t[1]+"$",s[t[1]])
					except:
						pass
	return template

def get_users_in_tweet(s):
	new=""

	if s.has_key("quoted_status")!=False:
		s['text']+=" "+s['quoted_status']['user']['screen_name']

	if s.has_key("retweeted_status")!=False:
		s['text']+=" "+s['retweeted_status']['user']['screen_name']

	new="@"+s['user']['screen_name']

	weew=s['text'].split(" ")
	for i in range(0,len(weew)):
		if "@" in weew[i] and weew[i]!="@"+twitter.screenname:
			new+=" "+weew[i]
	return new

def user(s):
	if s.has_key('user'):
		return s['user']['screen_name']
	else:
		return s['sender']['screen_name']

def get_focused_tweet():
	index=gui.interface.window.tweets.GetSelection()
	focused=gui.interface.window.focused
	return get_buffer_item(focused,index)

def parse_date(date):
	try:
		ti=datetime.datetime.now()
		tz=time.altzone
		date2=datetime.datetime.strptime(date.replace("+0000 ",""),"%a %b %d %H:%M:%S %Y")
		try:
			date2+=datetime.timedelta(seconds=0-tz)
		except:
			pass
		returnstring=""

		try:
			if date2.year==ti.year:
				if date2.day==ti.day and date2.month==ti.month:
					returnstring=""
				else:
					returnstring=date2.strftime("%m/%d/%Y, ")
			else:
				returnstring=date2.strftime("%m/%d/%Y, ")

			if returnstring!="":
				returnstring+=date2.strftime("%I:%M:%S %p")
			else:
				returnstring=date2.strftime("%I:%M:%S %p")
		except:
			pass
	except:
		return date
	return returnstring

def update_buffer_item(name,index,item):
	remove_buffer_item(name,index)
	insert_buffer_item(name,index,item)

def remove_buffer_item(name,index):
	for i in range(len(buffers)):
		if buffers[i].name==name:
			buffers[i].statuses.pop(index)
			if gui.interface.window.focused==name:
				gui.interface.window.tweets.Delete(index)

def insert_buffer_item(name,index,item):
	for i in range(len(buffers)):
		if buffers[i].name==name:
			buffers[i].statuses.insert(index,item)
			if gui.interface.window.focused==name:
				gui.interface.window.tweets.Insert(process_tweet(item),index)</code>

Wymuszanie robisz dopisując przy pierwszym ``` python (czyli ```python).


(arekk-99) #6

No dobra, ale to nie wyjaśnia, co jest w tej linijce 41 bodajże, że text=s[‘text’] jest nie tak, jak cokolwiek zmienię w tym pliku.


(Razi) #7

Próbowałeś debuggować? tzn. zatrzymać się przy tej linijce i sprawdzić co jest w s? Albo jak nie masz żadnego debuggera z breakpointami pod ręką (np. darmowy PyCharm Community), to próbowałeś wyprintować co jest w tej zmiennej? Ogarnąć to w try… catch (try… except) i wychwycić ten moment, w którym się sypie?

Wydaje mi się że po prostu próbujesz grzebać w kodzie, którego nie rozumiesz, bez znajomości języka i oczekujesz że wszystko będzie po prostu grało. Nie może być tak, że robisz jakąkolwiek zmianę i to przestaje działać. Zmiana musiała coś istotnego zmieniać, że przestało.


(arekk-99) #8

No to przecież tłumaczę, że tej linijki nie ruszałem.
tylko w tej pętli wyciągającej urle z tweetów dorzuciłem gotowca z kodu tej samej aplikacji, tylko we wcześniejszej wersji, zęby z twishorta wyciągało całe tweety i się posypało. Tak samo z configiem NOnetype has no attribute getitem, w wątku, który tworzyłem wcześniej. Też tam nigdzie nic nie ruszałem, a wystarczyło, ze wprowadziłem ręcznie zmianę w pliku.cfg i wszystko się zaczęło sypać.


(arekk-99) #9

A, no i oczywiście ten pycharm-community-edition jeszcze jakby był jakkolwiek dostępny dla osób z dysfunkcją wzroku, to może nawet sobie bym z niego z korzystał, no ale cóż. Nikt nie pomyślał, że napisze ilkadziesiąt linijek dodajac at-spi a nóż ktoś z tego kiedyś skorzysta…


(arekk-99) #10

No i też nie rozumiem jednej rzeczy. Jestem pewien, że do funkcji destroy_friendship przekazuję tylkonazwę użytkownika pozyskaną przy pomocy wyciągnięcia ID aktualnie podświetlonego tweeta na liście następnie wyciągnięcie ID użytkownika, tzn. jego nazwy przy pomocy przekazania ID tweeta do funkcji szukającej użytkowników

def user(s):
	if s.has_key('user'):
		return s['user']['screen_name']
	else:
		return s['sender']['screen_name']

def get_focused_tweet():
	index=gui.interface.window.tweets.GetSelection()
	focused=gui.interface.window.focused
	return get_buffer_item(focused,index)

Mam nadzieję, ze dziś dobrze zamieściłem kod.
Interpreter mi wywala, że w funkcji def unfollow(self,event) do funkcji twitter.Unfollow(user) przekazuję dwa parametry. Jestem pewien, że przekazuję tylko nazwę użytkownika. No chyba, że jakimś prawem nie wywołując funkcji twitter.unfollow(user) z jednym parametrem to self się tam dopisuje…

menu = wx.Menu()
		m_follow = menu.Append(1, "&Follow user", "follow user")
		self.Bind(wx.EVT_MENU, self.follow, m_follow)
		m_unfollow = menu.Append(-1, "&Unfollow user", "unfollow user")
		self.Bind(wx.EVT_MENU, self.unfollow, m_unfollow)
		self.menuBar.Append(menu, "&user")
#następnie
	def follow(self,event):
		t = buffer.get_focused_tweet()
		u = buffer.user(t)
		print(u) #wyświetla nazwę usera
		user = twitter.Follow(u)
	def unfollow(self, id):
		t = buffer.get_focused_tweet()
		u = buffer.user(t)
		user = twitter.Unfollow(u)
def Unfollow(user):
  twitter.destroy_friendship(user)

Coś tu robię faktycznie źle, że pluje o te 2 parametry?


(Razi) #11

Ehhh…
https://www.jetbrains.com/pycharm/, wielki przycisk DOWNLOAD NOW, potem pod COMMUNITY jest DOWNLAOD. Jaką ty masz dysfunkcję wzroku, ślepota?

No to przecież tłumaczę, że tej linijki nie ruszałem.

To tak jakbyś się na budowie tłumaczył, że dachu nie ruszałeś, sam się zawalił. Po tym jak rozwaliłeś ścianę nośną.

Nie musiałeś, wystarczy że gdzie indziej coś zmieniłeś i w tym s ląduje nie to, co powinno. Wszystko ma swoje przyczyny, niekoniecznie tam, gdzie występuje sam problem. Język nie jest niczemu winien, a wprowadzane modyfikacje, które nie są przygotowane na różne warunki. Nie można wprowadzać zmian i oczekiwać że będą ot tak działały. Trzeba przetestować, sprawdzić gdzie się sypie, naprawić i ewentualnie zabezpieczyć przed potencjalnymi przypadkami.

Widocznie Twitter zrobił większe zmiany i API wygląda inaczej i zmian musisz wprowadzić więcej niż myślałeś.

Witamy w programowaniu: wprowadzasz zmianę w pliku a, a zaczyna się sypać w pliku d :slight_smile:

Jestem pewien, że do funkcji destroy_friendship przekazuję tylko nazwę użytkownika pozyskaną przy pomocy wyciągnięcia ID

Jesteś 100% pewien? Wyprintuj do konsoli takie rzeczy. Najlepiej dodaj asserty, które sprawdzają poprawność argumentów i w razie czego wysypują program ze stosownym komunikatem.

Naucz się debugować w IDE. Nie rozumiem czemu kursy programowania rzadko wspominają o czymś takim.

Coś tu robię faktycznie źle, że pluje o te 2 parametry?

self „sam” się dopisuje gdy wywołujesz metodę na obiekcie. Jeśli Unfollow należy do obiektu twitter, to self jest dodawany przy wywołaniu.

Swoją drogą, to trzymaj się jednej metody nazywania, w pythonie używa się zwykle underscore, czyli wszystko małą literą (poza nazwami klas), a zamiast spacji podkreślenia.


(arekk-99) #12

To nie mój kod, więc się jakoś muszę dostosować do tego, co gościu pisze
printowałem u i jest tak, jak być powinno, tj. zwraca nazwę użytkownika.
Tak, ślepota :confused:
I wiesz co, jakoś mi to wcale nie przeszkadza :smiley:
Ale API jest aktualne, bo wszystko działa, tylko to text=coś tam już teraz do końca nie pamiętam. Wywaliłem to stamtąd, ściągnąłem poprzednią wersję z gita i bangla.

Wywaliłem self z Follow i nie działa. Error. Follow takes exactly 1 argument, 2 given.


(Razi) #13

To jak ty nie pamiętasz, to jak ktokolwiek może ci pomóc? Jeśli w tej linijce jest problem, to znaczy że którejś danej nie ma. MUSISZ SAM wydedukować co tam jest nie tak. Postaw tam try…except i badaj co się dzieje. Python na pewno daje całego stack trace’a. W IDE miałbyś jeszcze dostęp do wartości wszystkich zmiennych z całego stosu wywołań, co by bardzo ułatwiło sprawę.

W sensie z deklaracji? W deklaracjach metod ZAWSZE musi ten self być, bo w wywołaniu metody zawsze on jest wstawiany za pierwszy argument. W wywołaniach sam się dodaje.

BTW. PyCharm Community jest jeszcze dostępny w snapcrafcie, można go zainstalować z konsoli w Linuksie przez sudo snap install pycharm-community.

I nie zwalaj na język swojej nieznajomości tego języka. Python jest jednym z łatwiejszych języków, ale i on wymaga nauczenia się go.


(arekk-99) #14

Człowieku!
Mówię Ci, ze dla osoby takiej jak ja, czyli osoby z DYSFUNKCJĄ WZROKU uniemożliwiającą mi czytanie czegokolwiek z ekranu żaden pyharm-community nie jest dostępny, bo orca mi go po prostu nie czyta.
Nie ruszałem tej linijki o tekście, mówię.
z definicji funkcji wywaliłem self, tak jak ktoś tu już powiedział i wyrzuca błąd, że wymaga 1 parametru, a dostał 2.
Tak samo się dzieje, jak go tam dodam z tym, ze wtedy się dzieje tak w twitter.twitter.destroy_friendship(screen_name)


(krystian3w) #15

No to trochę lipa, ja mam nadzieje że się nie nabawie przez najbliższe 10 lat szkieł z -10 dioptrii (a już mam -3,25 i -2,75).


(Gruba_S) #16

Ja nie wiem, czy ja jestem jakiś niepojętny, czy Python tak ma, ze wali błędami tam, gdzie ich wcześniej nie było?

Nie, Wali błędami tam, gdzie rzeczywiście są.


(Razi) #17

W takim razie wybacz.

Nie zmienia to faktu, że jednak nie śledzisz zmian i brzmi to jakbyś zwalał winę za swoją niewiedzę i brak umiejętności język. Uwierz mi, że gdyby to język był problemem, nie osiągnąłby on aż takiej popularności i wsparcia.

Wątek się ciągnie, a ty nawet nie raczyłeś skopiować komunikatu błędu, zapewne to KeyError, bo zmienna s nie ma klucza text, bo Twitter zwrócił coś innego niż oczekiwałeś.

Tak samo się dzieje, jak go tam dodam z tym, ze wtedy się dzieje tak w twitter.twitter.destroy_friendship(screen_name)

BO KAŻDA METODA MUSI PRZYJĄĆ PIERWSZY PARAMETR self! Jest on dodawany automatycznie przy wywołaniu, więc musi być uwzględniony przy deklaracji. Jest w deklaracji, w wywołaniu sam się dodaje.


(arekk-99) #18

twitter.twitter.destroy_friendship(screen_name) to jest od twythona, więc jeśli oni nie mają w deklaracji tego wstawionego, no to chyba raczej z tym nic nie zrobię.
Tylko chciałbym zauważyć, że w tweepy wcześniej to działało normalnie, a naprawdę wystarczy, że zmieniłem tylko deklarację, tzn. Przepisałem ją na nowo tak, jak była wcześniej i naprawdę to po prostu nie chciało działać.
text=s[‘text’] dokładnie. Z tym, że zawsze działa. A wystarczy, ze ruszę jakąkolwiek linijkę i potem ją stamtąd wyrzucę, to i tak nie chce działać. Aha… Czyli ja robię źle, a i tak wykrywa błąd w linii, któa pół godizny temu działała normalnie.


(Razi) #19

Nie doczytałeś dokumentacji i w połączeniu nie znasz Pythona dość dobrze: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy.
Musisz podać to w formie twitter.destroy_friendship(screen_name=screen_name), bo przyjmowane to jest w parametrach, a one w argumentach nie są liczone, czy jakoś tak.

Sądziłem że sam napisałeś te API, bo nie podałeś wcześniej z jakiego korzystasz, albo że wcześniej działało i założyłem że tak po prostu jest OK.

text=s[‘text’] dokładnie. Z tym, że zawsze działa. A wystarczy, ze ruszę jakąkolwiek linijkę i potem ją stamtąd wyrzucę, to i tak nie chce działać. Aha… Czyli ja robię źle, a i tak wykrywa błąd w linii, któa pół godizny temu działała normalnie.

Kod to nie zbiór oddzielnych linii kodu. Wszystko stanowi jedność. Jak w samochodzie do baku wlejesz jakiś syf, to może ci pół silnika przestać działać i zasyfić możesz wydech. To samo jest w programowaniu: w jednym miejscu gdzieś nawalisz, sypie się reszta. Jeśli z samochodu wyjmę filtr powietrza, z dużym prawdopodobieństwem po godzinie siądzie mi turbo, choć jeszcze godzinę temu działało i nic z nim nie robiłem (nie mówiąc już o tym, co będzie się działo w cylindrach).

I nie, Python nie wykrywa błędu. Analizatory kodu to robią. Po prostu twój kod się sypie.


(arekk-99) #20

Dobra, faktycznie. Tam tak było, z tym, ze w poprzedniej wersji tego działało bez tego. No ale teraz faktycznie to działa. No oczywiście to mi nie rozwiązuje problemu z text=s[‘text’] no ale cóż. Nieważne. Dobrze, że chociaż to działa.
Serdeczne dzięki.