Bitte um Pythonisierung :-)

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
barrio
User
Beiträge: 30
Registriert: Dienstag 26. Februar 2013, 13:15

Hallo zusammen,

ich habe mir mittlerweile ein solides Halbwissen in Python angeeignet, soll heißen ich kriege einige meiner Ideen/Vorstellungen dann doch irgendwie zum Laufen. Nun würde ich gern meinen (Un-)Stil anhand dieses Scripts verbessern:

Code: Alles auswählen

#!/usr/bin/env python   


import os
import hashlib
import cherrypy
import pythoncom
import _thread
import win32com.client as win32
from mako.template import Template
from tkinter import *

class Root:
    ''' Probandencode-Eingabe '''
    @cherrypy.expose
    def index(self):
        return """<html>
        <head>
          <title>Fragebögen</title>
        </head>
        <body>
          <h1>Frageb&ouml;gen ausf&uuml;llen</h1>
          Bitte Probandencode eingeben:<br>
          <form action="fragebogen" method="POST">
          Code:&nbsp;
          <input type="text" name="code" size="12" maxlength="7">
          <input type="hidden" name="itemnr" value="-1">
          <input type="hidden" name="itemwert" value="-1">
          <input type="Submit"  value="Start">
          </form>
        </body>
        </html>"""

@cherrypy.expose
def fragebogen(itemwert, itemnr, code):
    itemnr = int(itemnr)
    itemnr += 1
    pythoncom.CoInitialize() # threads & COM
    aktuelles_verzeichnis = os.getcwd()

    #Auswertungsmaske unter Probandencode anlegen, sobald 1. Item angezeigt 
    if itemnr < 1:
        excel = win32.gencache.EnsureDispatch('Excel.Application')        
        wb = excel.Workbooks.Open(aktuelles_verzeichnis + r'\Testdiagnostik Auswertungsmaske.xlsx')
        excel.Visible = False
        ws = wb.Worksheets(1)
        excel.Application.DisplayAlerts = False
        wb.SaveAs(aktuelles_verzeichnis + '\\' + code + '.xlsx')
        excel.Application.Quit()
    #letzte Itemantwort in Exceltab eintragen
    else:
        excel = win32.gencache.EnsureDispatch('Excel.Application')
        wb = excel.Workbooks.Open(aktuelles_verzeichnis + '\\' + code + '.xlsx')
        excel.Visible = False
        ws = wb.Worksheets(1)
        ws.Range("B"+str(itemnr+6)).Value = itemwert #Werte in Spalte B ab Zeile 7
        excel.Application.DisplayAlerts = False
        wb.SaveAs(aktuelles_verzeichnis + '\\' + code + '.xlsx')
        excel.Application.Quit()

    pythoncom.CoUninitialize()

    # Itemliste anlegen
    itemtext = ['1. Item',
                '2. Item',
                '3. Item',
                '4. Item',
                '5. Item'] #...
               
    #Vorlage für Fragebogen
    mytemplate = Template("""<html>
      <head><title>Fragebogen</title></head>
        <body>
        <form method="POST"
        action="fragebogen">
        Code:<input type="text" name="code" value="${code}">
        <input type="hidden" name="itemnr" value="${itemnr}"><br><br>

        Instruktion<br>
        ${itemtext}<br><br>
        <input type="radio" name="itemwert" value="0">Antwort A<br>
        <input type="radio" name="itemwert" value="1">Antwort B<br>
        <input type="radio" name="itemwert" value="2">Antwort C<br>
        <input type="radio" name="itemwert" value="3">Antwort D<br>
        <input type="radio" name="itemwert" value="4">Antwort E<br><br>
        <input type="submit" value="Weiter"><br><br>
        </form></body>
    <html>""")

    #Item ausgeben
    return mytemplate.render(code=code, itemnr=str(itemnr),
                             itemtext=itemtext[itemnr])

# Testarea: ungeschützter Bereich
@cherrypy.expose
def free():
    return "This is a free area"

if __name__ == '__main__':
    server_an = False
    thread_an = False
    
    def thread_switch_server():
        global server_an
        
        if not server_an:
            server_an = True
            fenster.button["text"] = "STOP"
            fenster.label.config(text='Server ist AN')
            
            #Serverprozess bereits gestartet?
            if not thread_an == True:
                _thread.start_new_thread(server_config,())
            else:
                cherrypy.engine.start()
        else:
            server_an = False
            fenster.button["text"] = "START"
            fenster.label.config(text='Server ist AUS')
            cherrypy.engine.stop()

    def get_users():
        # 'test': 'test'
        return {'test':'ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff'}

    def encrypt_pwd(token):
        return hashlib.sha512(token.encode(encoding="utf-8")).hexdigest()
    
    def server_config():
        # Root passwortgeschützt
        conf = {'/': {'tools.basic_auth.on': True,
                      'tools.basic_auth.realm': 'Some site',
                      'tools.basic_auth.users': get_users,
                      'tools.basic_auth.encrypt': encrypt_pwd}}
        # URL-Mappings
        root = Root()
        root.fragebogen = fragebogen
        root.free = free

        # Server-IP, Port & SSL-Verschlüsselung
        cherrypy.config.update({'server.socket_host': '192.168.0.6',
                                'server.socket_port': 8090,
                                'server.ssl_certificate': './server.crt',
                                'server.ssl_private_key': './server.key',
                               })
        cherrypy.engine.autoreload.unsubscribe()
        cherrypy.quickstart(root, '/', config=conf)     

    # Server-GUI
    fenster = Tk()
    fenster.label=Label(fenster, text='Server ist AUS')
    fenster.label.pack()
    fenster.button = Button(master=fenster,
                            text='START',
                            command=thread_switch_server)
    fenster.button.pack()
    fenster.mainloop()
Als kurze Freitext-Erläuterung dazu: Fragebogenitems sollen über eine verschlüsselte & passwortgeschützte Verbindung im Browser serviert werden und die Antworten dann in eine bereits bestehende Excelmaske gepackt werden (sorry, aber Excel ist gesetzt, leider).

Wer es ausprobieren möchte und keine Lust hat ein Zertikat zu erstellen, here you go:

server.crt

Code: Alles auswählen

-----BEGIN CERTIFICATE-----
MIICATCCAWoCCQDYwq5UbWJ62zANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMB4XDTEyMDMxNDIxMDMyMloXDTEzMDMxNDIxMDMyMlowRTELMAkG
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu8ic
FFJZbp+U6L2HIEFPnblWGaECUQvBIjNAQqzmrMc7GY6BEAolC9g7mNi2D1JaYcxs
WgqjiypfW9tiOsybmoGDh2b+HsxkmtIWDM0anHCxbncJitCIrpqHp9Tu7Fvk8SrA
kKfu+3fQ/9ge8yDoa2t23/WKnG+nO7G/JuLyEJkCAwEAATANBgkqhkiG9w0BAQUF
AAOBgQCD5nRO8nzqlF/Q3wo+pJtHJjS88I6nZxhZTecmhZ3R4J6jo1V/RMysYYNt
zLK8m5QEv2P0SLmf5ysGam6Kd8PBGRxMWW1wbWnwxKyDoaso7vTK4eHzwrxgQk9w
pKnxiyt1k4P2vars13hdxAEQu11yJkzoMieHTyS+FxIUexUvTg==
-----END CERTIFICATE-----
server.key

Code: Alles auswählen

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC7yJwUUllun5TovYcgQU+duVYZoQJRC8EiM0BCrOasxzsZjoEQ
CiUL2DuY2LYPUlphzGxaCqOLKl9b22I6zJuagYOHZv4ezGSa0hYMzRqccLFudwmK
0Iiumoen1O7sW+TxKsCQp+77d9D/2B7zIOhra3bf9Yqcb6c7sb8m4vIQmQIDAQAB
AoGAfSF92BDT5WJToQ+Cdpzux8RTunpPB+CUTwzl2khK4oFUQYBzQlPwQcdSV1S5
ZNZUweytmwaR2k9fAd/bwiDL4m/iGfmerwD1LPaWlYufKPEKG2XBzCAytNTuAU3J
/UXqlQK5Ee4aCcmVrXPsjkPgunQM4hs7qQFJI+s0vPPRYT0CQQD3nFys2ScKfszP
DLMQelWbo+kxqYrThfnCzsHFWA7fJXsyBX23CR8L1Dy5RcBxUa4I8VATwpfv8V7a
MQtDJciLAkEAwiVXGq0agnC5I3xEx2b14ezuXDBWK/Ld+QH6ocTFLxa6oy+YY4Sd
4dilZwWAgef8QBkXJbGxkbw4xKDxDo8L6wJAHSj26QwxwtSn/gI63Efr6QZmogib
ZsmyXjTHMRxrs+/QEFYBNhsG4ve9pvwF69J4smjoy0rxZbqBNyTrdJ7wfQJAFwzh
45vrytLhWFI3xEj4JoO/5RgkEwG50wemHzDCjI2xSRCskhw7toXHVYz0rffCHkYc
VnBbeccUIlxNYoIfUwJBAKdrypQG/vu6xvRm4Y70K+IiOxzOCIflyT8KYI106jqt
0LfwMlVmtiGUr3tj+GEyi+FlisEJ7xaEHIu41yrcR/4=
-----END RSA PRIVATE KEY-----
Neben den stilistischen noch einige inhaltliche Fragen:

1. Unter WinXP SP3 mit Python 3.3 läuft das ganze problemlos, unter Win7 kommt ein "Could not create socket"-error. Dies soll wohl kein Bug sondern ein Sicherheitsfeature von Windoofs sein. Abhilfe soll z.B. sein, den Server als Dienst zu implementieren. Was meint ihr dazu und wie ginge das am einfachsten? Es gibt ein sniplet auf der cherrypy-Seite dazu, aber mein Script da einzubauen überfordert mich z.Zt...

2. Jetzt verstehe ich, warum alle so auf COM schimpfen. Das Mistvieh produziert machmal kryptische Fehler und dann läuft es plötzlich wieder, obwohl am Code nichts geändert wurde :evil: Leider habe ich bislang keine Alternative gefunden. Sowohl xltools als auch openpyxl zerschießen mir die Formatierung der bereits erstellten Auswertungmaske. Hat da jemand noch ne Idee, wie ich hier auf COM verzichten könnte?

3. Für wie sicher haltet ihr diese Umsetzung, wenn man den Server in einem verschlüsselten WLAN ohne Internetanbindung betreiben will? Welche Angriffspunkte gäbe es?

4. Ich würde gern ganz auf OOP verzichten, habe es aber nicht geschafft, das root-mapping für eine einfache Funktion statt Klasse zu schreiben, obwohl das gehen sollte...

5. Die beiden globals server_an & thread_an würd ich auch gern loswerden...

Vielen Dank schonmal für Eure konstruktive Kritik & Unterstützung vorab!

barrio
> (...(lambda...(it-schemes-i-must-be-jailed-in-braces? code)...))))))))))))))))))))))))))
#t
barrio
User
Beiträge: 30
Registriert: Dienstag 26. Februar 2013, 13:15

Da mir bislang niemand antwortet mach ich das mal z. T. selber :D

Für 1. habe ich eine recht bequeme Lösung gefunden, diese heißt NT service installer und macht ein beliebiges Python oder JAVA-Script zum Dienst, ohne Umwandlung in eine exe vorher. Für Interessierte, hier der Link: https://sites.google.com/site/conort/ru ... sntservice.

Das Sniplet ist ja vielleicht schon etwas speziell, dennoch kann ich mir nicht vorstellen, dass insbesondere zu den Sicherheitsaspekten unter 3. niemand von den Netzwerk- und Webspezies hier ne Meinung hat?!? Oder mach ich was anderes falsch, weshalb mir keiner antwortet :? ?

LG barrio
> (...(lambda...(it-schemes-i-must-be-jailed-in-braces? code)...))))))))))))))))))))))))))
#t
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

  • Templates hat man üblicherweise nicht im Quelltext.
  • Der Unterstrich bei `_thread` sollte eigentlich Hinweis genug sein es nicht zu benutzen.
  • Auf die GUI aus einem Thread zuzugreifen ist eine schlechte Idee, da diese normalerweise nicht threadsafe sind.
  • Threads in einer Web Anwendung zu benutzen ist i.d.R. eine schlechte Idee aber verkraftbar wenn man Kontrolle über das Deployment hat.
  • Eine GUI zu benutzen ist schon eher seltsam in diesem Kontext.
  • Pfade setzt man mit `os.path.join()` zusammen.
  • sha512 taugt nicht um Passwörter zu hashen, nimm bcrypt oder pbkdf2.
  • Sternchen-Importe wie ``from tkinter import *`` sind eine schlechte Idee. Importiere explizit oder kürze den Namespace mit ``import tkinter as tk`` ab.
  • Verwende Englisch für Bezeichner und wenn es wirklich nicht anders geht nimm Deutsch aber nicht beides.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Ui, da hat jemand aber einen schönen Trojaner geschrieben. Werden Excel-Dateien im Autostartverzeichnis auch automatisch ausgeführt?
Benutzeravatar
MikeDee
User
Beiträge: 31
Registriert: Samstag 5. November 2011, 12:41

Sorry für Off-Topic, aber @DasIch

bitte benutze demnächst ' oder " aber nicht `. Das sieht einfach nicht schön aus und ist die falsche Vewendung für diese Zeichen, über ` ` will ich gar nicht reden.
BlackJack

@MikeDee: Die Zeichen(kombinationen) ` und `` werden hier von einigen Leuten (mich eingeschlossen) als Auszeichnung in der Bedeutung von reStructuredText verwendet. Ob das nun eine falsche Verwendung der Zeichen ist, hängt also vom Kontext ab, in dem man diese Frage betrachtet.
Benutzeravatar
MikeDee
User
Beiträge: 31
Registriert: Samstag 5. November 2011, 12:41

BlackJack hat geschrieben:@MikeDee: Die Zeichen(kombinationen) ` und `` werden hier von einigen Leuten (mich eingeschlossen) als Auszeichnung in der Bedeutung von reStructuredText verwendet. Ob das nun eine falsche Verwendung der Zeichen ist, hängt also vom Kontext ab, in dem man diese Frage betrachtet.
Okay, wenn ihr einen Grund dazu habt ist es, für mich, in Ordnung und will es euch gar nicht raus reden. Habe es nur erwähnt, weil ich es anders gelernt habe.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

MikeDee hat geschrieben:Okay, wenn ihr einen Grund dazu habt ist es, für mich, in Ordnung und will es euch gar nicht raus reden. Habe es nur erwähnt, weil ich es anders gelernt habe.
Du hast das vermutlich im Kontext von Zitaten gelernt, aber hier wird `foo` oder ``foo`` oft verwendet um darauf hinzuweisen dass es sich um Quelltext-Zitate handelt. In der Tat werden diese Auszeichnungsarten oft von Markup-Formaten wie reST oder Markdown verwendet um "Schreibmaschinenschrift" einzuleiten, also ne Schriftart fester Breite, wie das oft in Texteditoren zum Programmieren verwendet wird.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
barrio
User
Beiträge: 30
Registriert: Dienstag 26. Februar 2013, 13:15

</OT> <!-- Sorry, wenn ich jetzt wieder auf das Thema zurückomme :) -->

@DasIch

Vielen Dank erstmal für Deine Kommentare!
DasIch hat geschrieben:
  • sha512 taugt nicht um Passwörter zu hashen, nimm bcrypt oder pbkdf2.
  • Sternchen-Importe wie ``from tkinter import *`` sind eine schlechte Idee. Importiere explizit oder kürze den Namespace mit ``import tkinter as tk`` ab.
  • Eine GUI zu benutzen ist schon eher seltsam in diesem Kontext.
Könntest Du mir zu 1. & 2. noch ein bischen erklären wieso? Ersteres hab ich aus einem Pythonbuch...

3. Die GUI deshalb weil der Server nur an sein soll, wenn grad jemand einen Fragebogen ausfüllt.
Sirius3 hat geschrieben:Ui, da hat jemand aber einen schönen Trojaner geschrieben. Werden Excel-Dateien im Autostartverzeichnis auch automatisch ausgeführt?
Erstere Unterstellung finde ich ziemlich dreist. Zu Satz 2 nein. Vielleicht könntest Du ja auch konstruktiv was beitragen, oder ansonsten Rüdiger Hoffman befolgen...
> (...(lambda...(it-schemes-i-must-be-jailed-in-braces? code)...))))))))))))))))))))))))))
#t
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

barrio hat geschrieben:
DasIch hat geschrieben:
  • sha512 taugt nicht um Passwörter zu hashen, nimm bcrypt oder pbkdf2.
  • Sternchen-Importe wie ``from tkinter import *`` sind eine schlechte Idee. Importiere explizit oder kürze den Namespace mit ``import tkinter as tk`` ab.
Könntest Du mir zu 1. & 2. noch ein bischen erklären wieso? Ersteres hab ich aus einem Pythonbuch...
Ad 1) SHA512 ist eine Allzweck-Kryptographische-Hashfunktion und die sind nunmal darauf ausgelegt schnell, richtig schnell zu sein. Das Problem ist, dass es damit sehr anfaellig gegen Bruteforce Angriffe ist. Die beiden Alternativen haben den Zweck das Hashen langsam und aufwaendig zu machen um das zu verhindern. Ich werfe aber nochmal scrypt in den Ring, da es auch eine hohe Speicherkomplexitaet hat.

Ad 2) Mit Sternchen-Importen laedst du den gesamten Namensraum und ueberschreibst im schlimmsten Fall Namen und hast schwer verstehbare Fehlermeldungen.
Antworten