Törmäsin vallan mielenkiintoiseen ongelmaan tehdessäni jälleen kerran uutta IRC-systeemiä pythonilla. jouduin päivittämään PYTHONversioksi kolmosen, koska eräs grafiikkakirjasto noin vaati, ja törmäsin koodissani:
# -*- coding:cp1252 -*- import socket sok = socket.socket() serveri = "irc.quakenet.org" portti = "6667" nick = "HerraP" kayttajanimi = "HerraP" oikeanimi = "HerraP" kanavat = ['#kanava1', '#kanava2'] def paa(serveri, portti, nick, kayttajanimi, oikeanimi, kanavat, sok): sok.connect((serveri, int(portti))) sok.send('USER ' + str(kayttajanimi) + ' ' + str(nick) + ' ' + str(serveri) + ' :' + str(oikeanimi) + '\r\n').encode('utf8') #sok.send('USER ' + kayttajanimi + ' ' + nick + ' ' + serveri + ' :' + oikeanimi + '\r\n') sok.send('NICK ' + nick + '\r\n') for kanava in kanavat: sok.send('JOIN ' + kanava + '\r\n') while 1: teksti = sok.recv(4096) print(teksti) if teksti[0:4] == 'PING': sok.send('PONG ' + teksti.split() [ 1 ] + '\r\n') paa(serveri, portti, nick, kayttajanimi, oikeanimi, kanavat, sok)
ongelmaan
Traceback (most recent call last): File "C:\Documents and Settings\Lotto\Työpöytä\seta.py", line 22, in <module> File "C:\Documents and Settings\Lotto\Työpöytä\seta.py", line 12, in paa TypeError: must be bytes or buffer, not str >>>
Mistähän kummasta tämä version 2.6 ja 3.1.1 versioiden ero mahtaa johtua?
Python 3:ssa tekstit ovat lähtökohtaisesti Unicode-tekstejä, ja jos haluat niistä tavuja (kuten tuossa tapauksessa), ne täytyy enkoodata jotenkin. Vilkaise Python-oppaan merkistöliitettä, asia luultavasti pätee suurelta osin myös Python 3:een, kunhan muistat tämän viestin ensimmäisen lauseen. Jos olet kärsimätön, oppaan lopussa on suoraan tarkoitukseesi soveltuva esimerkki.
Lotto kirjoitti:
mysliversioksi
Miten se mysli tähän juttuun liittyy?
Okei, tämä:
# -*- coding:ascii-*- import socket sok = socket.socket() serveri = str("irc.quakenet.org") portti = "6667" nick = str("seta") kayttajanimi = str("setamies") oikeanimi = str("setamies") kanavat = ['#pena', '#vapaadyykkarit'] def paa(serveri, portti, nick, kayttajanimi, oikeanimi, kanavat, sok): sok.connect((serveri.encode('UTF-8'), int(portti))) sok.send('USER ' + kayttajanimi.encode('UTF-8') + ' ' + nick.encode('UTF-8') + ' ' + serveri.encode('UTF-8') + ' :' + oikeanimi.encode('UTF-8') + '\r\n') sok.send('NICK ' + nick + '\r\n') for kanava in kanavat: sok.send('JOIN ' + kanava + '\r\n') while 1: teksti = sok.recv(4096) print(teksti) if teksti[0:4] == 'PING': sok.send('PONG ' + teksti.split() [ 1 ] + '\r\n') paa(serveri, portti, nick, kayttajanimi, oikeanimi, kanavat, sok)
muutti tilannetta näion:
Traceback (most recent call last): File "C:\Documents and Settings\Lotto\Työpöytä\seta.py", line 21, in <module> File "C:\Documents and Settings\Lotto\Työpöytä\seta.py", line 12, in paa TypeError: Can't convert 'bytes' object to str implicitly
Ja tuosta myslijutusta, taisin olla ajatuksissa ku just ennen viestiä kasannu myslikantaa :D
Edelleenkin ne tekstit ovat oletuksena Unicode-tekstejä ja ne pitää enkoodata. Kannattaisi varmaan ensin muodostaa koko teksti ja vasta sitten enkoodata kaikki kerralla, siis sok.send((a+b+c).encode('UTF-8'))
. Vastaavasti recv-funktion perään kuuluisi decode, mutta toki ensin täytyy tunnistaa lähettäjän merkistö. IRC-protokolla sinänsä on ASCII-pohjainen, joten erikoismerkit esiintyvät vain muussa datassa kuten viesteissä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.