Seite 1 von 1

Tuple aus Dictionaries in einem String parsen

Verfasst: Montag 15. Juli 2013, 22:50
von lexaiden
Hallo,

ich will in einem Python-Script mit einem PHP-Script auf einem Webserver Daten austauschen. Ich dachte mir, am einfachsten wäre es, wenn ich im PHP-Script die Daten so aufbereite das ich sie in Python einfach in eine Variable laden kann. Ich habe mir also einen String im PHP-Script gebaut, der in Python einem tuple aus dicts entspricht und diesen PHP-String dann per printf (über http) an das Python-Script verschickt.

In Python kommt der String auch klaglos an und sieht so aus:

Code: Alles auswählen

print(rcvData)
"({'id':507,'name':'test'},{'id':796,'name':'xyz'},{'id':13,'name':'Ich bin ein Name'})"
Die Variable "rcvData" hat den Type String und jetzt kommt mein Problem, wie kann ich das einfach in eine Variable laden, die dann ein Tuple aus Dictionaries ist?

Wenn ich den empfangenen String nehme und ihn in den Quellcode packe, z.B.:

Code: Alles auswählen

t = ({'id':507,'name':'test'},{'id':796,'name':'xyz'},{'id':13,'name':'Ich bin ein Name'})
Dann ist "t" vom Type Tuple und enthält Dicts.

Falls meine Formatierung des Strings in PHP unglücklich ist, kann ich das auch problemlos ändern, bin für jeden Hinweis/Tipp dankbar!

Hier mein Python-Script (Minimalbeispiel):

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import urllib2, urllib

trxData=[('one','1'),('two','2')]
trxData=urllib.urlencode(trxData)
path='http://localhost/py.php'
request=urllib2.Request(path, trxData)

response=urllib2.urlopen(request)
rcvData = response.read()
print(rcvData)

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Montag 15. Juli 2013, 22:58
von EyDu
Hallo und willkommen im Forum!

Schau dir mal das json-Modul an, das sollte dein Problem lösen.

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Montag 15. Juli 2013, 23:02
von BlackJack
@lexaiden: Du solltest nicht anfangen selber Formate zu erfinden, oder sprachspezifische zusammen zu basteln. Für so etwas bietet sich zum Beispiel JSON an. Bei Python gibt es dafür das `json`-Modul in der Standardbibliothek und bei PHP gibt es sicher auch etwas, denn JSON ist aus der Webentwicklung heutzutage ja nicht mehr wegzudenken.

Edit: http://php.net/manual/en/book.json.php

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Montag 15. Juli 2013, 23:35
von lexaiden
Hmmmm, stimmt, da gabs ja noch JSON *ditsch*. Muss leider auch noch gestehen ich hab es auch schon mal verwendet - ist allerdings schon etwas her. Naja, Wald, Bäume usw. - verstehste? :roll:

Danke Jungs!

Werde es dann mit JSON machen, das hat nicht mehr Overhead als meine angedachte Lösung, wenn ich das so Vergleiche. Aber rein Interesse halber, wäre mein Ansatz da oben - ohne jetzt ein riesen Fass (Schleifen, etc.) auf zu machen - lösbar?

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Dienstag 16. Juli 2013, 06:15
von snafu
lexaiden hat geschrieben:Aber rein Interesse halber, wäre mein Ansatz da oben - ohne jetzt ein riesen Fass (Schleifen, etc.) auf zu machen - lösbar?

Code: Alles auswählen

import ast
ast.literal_eval(dein_string)
Aber wie gesagt: Der übliche und dringendst zu empfehlende Weg ist JSON, denn JSON nutzt z.B. eine einheitliche Schreibweise für Wahrheitswerte (true vs. True vs. TRUE) oder Nullzeiger (NULL vs. null vs. None). Es ist eben einfach ein festes Format und tut auch nicht weh.

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Dienstag 16. Juli 2013, 08:19
von BlackJack
@lexaiden: Auf der Python-Seite würde ich einen Blick in das requests-Modul werfen. Das ist eine wesentlich schönere API über `urllib` & Co aus der Standardbibliothek:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests

def main():
    response = requests.get(
        'http://localhost/py.php', params={'one': '1', 'two': '2'}
    )
    received_data = response.json()
    print(received_data)


if __name__ == '__main__':
    main()

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Dienstag 16. Juli 2013, 10:32
von lexaiden
@snafu
Das "ast.literal_eval" hab ich gestern getestet und es hat nicht funktioniert, jetzt gerade nochmal getestet und es geht. Möchte mal wissen was ich gestern anders gemacht hab an 'nem Zweizeiler :? , den alten Codeschnipsel hab ich leider nicht behalten. Danke auf alle Fälle.

@BlackJack
Das sieht deutlich schicker aus, ich les es mir mal durch, Danke.

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Donnerstag 18. Juli 2013, 23:08
von lexaiden
Also JSON Daten vom PHP-Script aus an das Python-Script senden klappt wunderbar, wollte jetzt auch die Daten vom Python-Script zum PHP-Script mit JSON kodieren, aber das will nicht.

Ich hab mir eine Klasse gemacht, die sämtliche Kommunikation beinhalten soll, angefangen hab ich jetzt mit dem Login. Die Parameter "user" und "password" kommen von der GUI, diese sollen jetzt mit JSON kodiert an das PHP-Script geschickt werden, aber dort kommt nichts an. Wenn ich die JSON kodierung weglasse, kommen die Daten einwandfrei bei PHP an.

Code: Alles auswählen

import requests
import json
# from PyQt4 import QtGui, QtCore  # old imports
from python_qt_binding import QtGui, QtCore  # @UnresolvedImport @UnusedImport
from satConstances import * # @UnusedWildImport

class satCom:
    def __init__(self):
        self.dataPost = {"user" : "",
                         "password" : "",
                         "phpSessionID" : "",
                         "phpSessionTimeout" : 0,
                         "loggedIn" : False,
                         "request":""}

    def __del__(self):
        pass

    def checkLogin(self, user, password):
        self.dataPost["user"] = user
        self.dataPost["password"] = password
        self.dataPost["request"] = ("checkLogin",)

        print("\n### json.dumps(self.dataPost)") # debug
        print(json.dumps(self.dataPost)) # debug

        retval = requests.post(url, data=json.dumps(self.dataPost), verify=pemFile)

        print("\n### retval.text - mit json") # debug
        print(retval.text) # debug
        #retval.json() # debug

        print("\n### self.dataPost") # debug
        print(self.dataPost) # debug

        retval = requests.post(url, data=self.dataPost, verify=pemFile)

        print("\n### retval.text - ohne json") # debug
        print(retval.text) # debug
        #retval.json() # debug

        if retval["phpSessionID"] > 0:
            self.phpSessionID = retval["phpSessionID"]
            self.phpSessionTimeout = retval["phpSessionTimeout"]
            self.loggedIn = True

Hier mal die Ausgabe auf der Python console (Die Zeilen mit einem ">" davor ist quasi die Ausgabe von PHP):

Code: Alles auswählen

### json.dumps(self.dataPost)
{"loggedIn": false, "phpSessionTimeout": 0, "request": ["checkLogin"], "phpSessionID": "", "user": "", "password": ""}

### retval.text - mit json
>hallo
>Array
>(
>)
>"Kein Benutzer\/Passwort \u00fcbermittelt"

### self.dataPost
{'loggedIn': False, 'phpSessionTimeout': 0, 'request': ('checkLogin',), 'phpSessionID': '', 'user': u'', 'password': u''}

### retval.text - ohne json
>hallo
>Array
>(
>    [loggedIn] => False
>    [phpSessionTimeout] => 0
>    [request] => checkLogin
>    [phpSessionID] => 
>    [user] => 
>    [password] => 
>)
>"Benutzer nicht in DB gefunden,: 0"
Im PHP-Script steht gerade (unteranderem) zu debug Zwecken das:

Code: Alles auswählen

echo "hallo\n";
print_r($_POST);
...daher das "Hallo" in der Ausgabe ;-)

Kann mir mal bitte wer 'nen Tipp geben, warum keine POST Daten gesendet werden, wenn diese JSON kodiert sind? Ich finde eigentlich das mein Code ziemlich genau dem entspricht, was die Doku sagt: http://de.python-requests.org/de/latest ... rte-header Mal davon abgesehen, das ich keinen eigenen Header nutze. Aber auch das habe ich schon probiert und es bringt gar nix.

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Donnerstag 18. Juli 2013, 23:20
von Sirius3
@lexaiden: woher soll PHP bitte schön wissen, wie Deine POST-Daten kodiert sind!? Wenn Du irgendeine beliebige Byte-Folge schickst, kann ja nicht auf wundersame Weise der Computer raten, wie Du meinst, dass es richtig wäre.
Raw-Daten nehmen:

Code: Alles auswählen

$data = file_get_contents('php://input'); 
und selbst decodieren.

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Donnerstag 18. Juli 2013, 23:37
von lexaiden
Danke Sirius3, das war der entscheidende Tipp.

So in Python

Code: Alles auswählen

retval = requests.post(url, data={"json":json.dumps(self.dataPost)}, verify=pemFile)
Dann gehts so in PHP

Code: Alles auswählen

$data = json_decode($_POST["json"]);
print_r($data);

Re: Tuple aus Dictionaries in einem String parsen

Verfasst: Freitag 19. Juli 2013, 06:29
von Sirius3
@lexaiden: ̣... und verpackst Deine Daten gleich zweimal. Die saubere Lösung steht ja schon in Deiner verlinkten Doku. Setze den richtigen »Content-Type« und parse in Deinem PHP-Skript je nach »Content-Type« die POST Daten.