QString im Unicode?

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.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@snafu: In Bezug auf das Format-String. ich dachte mir einfach, dass ich alle Format-String in einem Schlag in unicode() umwandle, und nicht in jedem einzelnen Format-String ein "u" davor setze. Da hätte ich am Ende mehr "u"s als ich möchte. Daher habe ich es so erledigt. Aber wo genau wird nun erst ein Bytestring und dann erst ein Unicode erzeigt? Meinst du den Punkt in der log_in()-Funktion, wo ich jedes einzelne QString in unicode() umwandle?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Alle Format-Strings? Du hast einen einzigen Format-String! Das andere sind die Argumente für den Format-String - also dass, was eingesetzt werden soll. Und man kann das "u" nur verwenden, wenn man selbst einen String mittels Literalen erzeugt. Für deine anderen Strings würde das "u" nicht funktionieren, da sie ja erst zur Laufzeit bekannt sind.

Den Bytestring hast du immer dann, wenn du unter Python 2 einen String mittels String-Literalen erzeugst. Somit erzeugt ``unicode('spam')`` den Bytestring "spam". Wenn man diesen Bytestring an die `unicode()`-Funktion übergibt (was in dem Fall ja auch passiert), dann liefert sie einen Unicode-String zurück. Im Gegensatz dazu würde ein ``u'spam'`` direkt den Unicode-String erzeugen.

Und wie kommst du jetzt darauf, dass ein `unicode()`-Aufruf auf einen `QString` einen Bytestring als Zwischenschritt erzeugt? Es wurde doch schon erklärt, dass gerade dies *nicht* passiert.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@snafu: Dann habe ich dich falsch gelesen. Ich nahm an, dass du bei mir einen sogenannten "Zwischenschritt" entdeckt hast. Aber zu Sirius3s Anmerkung, das mit dem Passwort. Hat es sich hiermit erledigt? Er schrieb ja was von Kodierung. Ich zitiere ihn mal:
Sirius3 hat geschrieben:Außerdem handelt es sich um eine URL, das heißt, Du mußt Sonderzeichen (die ja v.a. in Passwörtern vorkommen können) kodieren.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich war gerade mal so frei, und habe chinesische Zeichen in meine Anmelde-Maske eingegeben. Alle Variablen und Strings sind ja nun in unicode() umgewandelt werden. Raus kam dabei folgende Fehlermeldung:
Traceback (most recent call last):
File "D:\Dan\Python\xarphus\xarphus\frm_db_login.py", line 170, in disable_connect_bitton
self.log_in()
File "D:\Dan\Python\xarphus\xarphus\frm_db_login.py", line 202, in log_in
database_name)
File "D:\Dan\Python\xarphus\xarphus\core\manage_mysql.py", line 155, in connect_to_mysql
Base.metadata.create_all(engine)
File "C:\Python27\lib\site-packages\sqlalchemy\sql\schema.py", line 3634, in create_all
tables=tables)
File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1851, in _run_visitor
with self._optional_conn_ctx_manager(connection) as conn:
File "C:\Python27\lib\contextlib.py", line 17, in __enter__
return self.gen.next()
File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1844, in _optional_conn_ctx_manager
with self.contextual_connect() as conn:
File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 2035, in contextual_connect
self._wrap_pool_connect(self.pool.connect, None),
File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 2070, in _wrap_pool_connect
return fn()
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 376, in connect
return _ConnectionFairy._checkout(self)
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 708, in _checkout
fairy = _ConnectionRecord.checkout(pool)
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 480, in checkout
rec = pool._do_get()
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 1055, in _do_get
self._dec_overflow()
File "C:\Python27\lib\site-packages\sqlalchemy\util\langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 1052, in _do_get
return self._create_connection()
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 323, in _create_connection
return _ConnectionRecord(self)
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 449, in __init__
self.connection = self.__connect()
File "C:\Python27\lib\site-packages\sqlalchemy\pool.py", line 602, in __connect
connection = self.__pool._invoke_creator(self)
File "C:\Python27\lib\site-packages\sqlalchemy\engine\strategies.py", line 97, in connect
return dialect.connect(*cargs, **cparams)
File "C:\Python27\lib\site-packages\sqlalchemy\engine\default.py", line 385, in connect
return self.dbapi.connect(*cargs, **cparams)
File "C:\Python27\lib\site-packages\pymysql\__init__.py", line 88, in Connect
return Connection(*args, **kwargs)
File "C:\Python27\lib\site-packages\pymysql\connections.py", line 644, in __init__
self._connect()
File "C:\Python27\lib\site-packages\pymysql\connections.py", line 838, in _connect
self._request_authentication()
File "C:\Python27\lib\site-packages\pymysql\connections.py", line 1007, in _request_authentication
_scramble(self.password.encode('latin1'), self.salt)
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-2: ordinal not in range(256)
Eine Verdammt lange Fehlermeldung :shock:
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: die große Frage ist, ob mysql überhaupt etwas von Encoding weiß. CREATE USER erlaubt die Angabe von Unicode-Username und -Password, wie das die Connection-URL umsetzt müßte man testen.
Ein korrekte URL sähe sowieso so aus:

Code: Alles auswählen

import urllib
def quote_unicode(value):
    return urllib.quote(unicode(value).encode('utf-8'), safe='')

def make_url(self):
        server_host = quote_unicode(self.ui_login.lineEdit_sevrer_host.text())
        username = quote_unicode(self.ui_login.lineEdit_username.text())
        password = quote_unicode(self.ui_login.lineEdit_password.text())
        database_name = quote_unicode(self.ui_login.lineEdit_database_name.text())
        port = int(self.ui_login.lineEdit_port.text())
           
        connection_url = b'{db_sys}+{db_driver}://{user}:{password}@{host}:{port}/{db}'.format(
            db_sys=dbm_system, db_driver=dbm_driver, user=username, password=password,
            host=server_host, port=port, db=database_name)
 
karolus
User
Beiträge: 141
Registriert: Samstag 22. August 2009, 22:34

Hallo

Vieleicht hilfts ja wenn du Zeile 105 der zuletzt angemeckerten Datei änderst:

Code: Alles auswählen

DEFAULT_CHARSET = 'utf-8'
[/size]

Quark:
Änder Zeile 1007:

Code: Alles auswählen

            _scramble(self.password.encode('utf-8'), self.salt)
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo karolus und Sirius3:

in diesem Beitrag habe ich insgesamt zwei Arten von create_engine vorgestellt, einmal die zusammengestückelte und einmal die mit dem Format-String:

Code: Alles auswählen

       # version 1
        engine = create_engine(dbm_system+'+'+dbm_driver+'://' + db_user + ':' + db_passwd + '@' + db_host + ':' + db_port + '/' + db_name,
             encoding='utf8', echo=True)

       # version 2
        engine = create_engine(unicode('{db_sys}+{db_driver}://{user}:{password}@{host}:{port}/{db}').format(
                                                                     db_sys=dbm_system,
                                                                     db_driver=dbm_driver,
                                                                     user=db_user,
                                                                     password=db_passwd,
                                                                     host=db_host,
                                                                     port=db_port,
                                                                     db=db_name,
                                                                     connect_args = {'time_zone': +'00:00'},
                                                                     encoding=utf8',
                                                                     echo=(True)))
Und in beidem wird auch der Encoding mit angegeben. In beiden Versionen fiel mir ein unterschiedliches Verhalten auf. In der zusammengestückelten Version wird nach einer erfolgreichen Anmeldung das Echo mit ausgespuckt sobald True gesetzt ist. Im String-Format erscheint kein Echo. Also ging ich davon aus, dass dort nichts unternommen wird, und auch das encoding vermutlich nicht greift. Also nahm ich die zerstückelte Version, und meldete mich nochmal mit chinesischen Zeichen an. Alles wunderbar.

Aber ich möchte deine Version auch verstehen, Sirius3, daher versuche ich mal mit meinen Worten nachzuvollziehen:

Code: Alles auswählen

import urllib
def quote_unicode(value):
    return urllib.quote(unicode(value).encode('utf-8'), safe='')
Hier wird eine Funktion erstellt, mit dem Argument value. Mit Hilfe von der urllib.quote()-Methode wird ein Argument zunächst in utf--8 enkodiert, und anschließend in unicode() umgewandelt, und was passiert mit safe?

Code: Alles auswählen

def make_url(self):
        server_host = quote_unicode(self.ui_login.lineEdit_sevrer_host.text())
        username = quote_unicode(self.ui_login.lineEdit_username.text())
        ...
Und die QStrings sind hier die value-Argumente, die der quote_unicode() übergeben und anschließend von der Funktion nach der Verarbeitung zurückgegeben werden. Ich hoffe, ich habe alles richtig verstanden.

@karolus: Die Zeilen, die du angegeben hast, gehören ja einer Bibliothek. Aus Angst und als Anfänger werde ich in keiner Bibliothek rumbasteln. Dazu bin ich zu unerfahren und zu neu in der Materie. Aber trotzdem vielen Dank für deinen Ratschlag.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: wenn Du Deiner beiden Versionen anschaust, wirst Du merken, dass sie unterschiedliche Argumente an create_engine übergeben. Das liegt an einer falsch gesetzten Klammer in Version 2. Du liest die Funktion quote_unicode falsch, nämlich von außen nach innen. Ausdrücke werden aber immer von innen nach außen gelesen: value wird zuerst in ein unicode-Objekt umgewandelt, dieses wird utf8 kodiert und alle Sonderzeichen durch quote in %-Sequenzen umgewandelt.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Du hast Recht, in Version zwei sind die Argumente tatsächlich unterschiedlich. Du sagtest, dass eine Klammer falsch gesetzt sei. Heißt das, dass Zeile 14-16 vor .format gepackt werden müssen?

Also etwa so?

Code: Alles auswählen

   engine = create_engine(unicode('{db_sys}+{db_driver}://{user}:{password}@{host}:{port}/{db}', connect_args = {'time_zone': +'00:00'},
                                                                     encoding=utf8',
                                                                     echo=(True)).format(
                                                                     db_sys=dbm_system,
                                                                     db_driver=dbm_driver,
                                                                     user=db_user,
                                                                     password=db_passwd,
                                                                     host=db_host,
                                                                     port=db_port,
                                                                     db=db_name))
Und zu deinem Vorschlag. Sollte ich deinen Vorschlag trotzdem mit übernehmen oder hätte es sich hiermit erledigt?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Alter Schwede...! Also ich bin raus. Technisches K.O. bzw Brainfuck! :lol:
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@snafu: Was habe ich falsch gemacht? Ging ich dir auf dem Zünder?
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Steck es doch nicht alles in eine Zeile, dann wird dir die Zuordnung klarer.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: so wird das nichts.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Ja, die Klammer habe ich eindeutig falsch gesetzt.
Antworten