Python Create Local Server Environment Generate QR Code

Keywords: Python QRCode socket Web Server

1. Requirements

The company wants to make an H5 mobile adapter page. Because of technical problems, H5 is outsourced. Each time the front-end gives us the source code, we pass the source code to the server for others to access to see if there is a bug. Isn't that troublesome?Some people say that they can let the front end be hosted on their servers first, and the source code will not end after we have checked it, yeah!Everyone wants this, but...

Is it better to have direct access to the local environment?The problem is that our program doesn't have time to dock with the H5 front end at this time, which wastes both our time and theirs.So develop a service server with testers directly involved so that we can divide up our work perfectly.

 

2. Python Build web Server

Python comes with an http.serrver package that makes it easy to set up a web server

Official website: https://docs.python.org/3/library/http.server.html?highlight=httpserver#http.server.BaseHTTPRequestHandler

Reference resources:

http://www.cnblogs.com/xuxn/archive/2011/02/14/build-simple-web-server-with-python.html

http://blog.csdn.net/kevin_darkelf/article/details/40979545

http://blog.csdn.net/tianmohust/article/details/7689414

 

 

# return Html page
class MyHttpBaseHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print(self.path)
        enc = "UTF-8"
        encoded = ''.join(self.path).encode(enc)
        f = io.BytesIO()
        f.write(encoded)
        f.seek(0)
        self.send_response(200)
        self.send_header("Content-type", "text/html; charset=%s" % enc)
        self.send_header("Content-Length", str(len(encoded)))
        self.end_headers()
        shutil.copyfileobj(f, self.wfile)

    # This method serves the 'POST' request type, only allowed for CGI scripts.
    def do_POST(self):
        pass


# return  static  -m  eg:python -m http.server 8080
class MyHttpSimpleHandler(SimpleHTTPRequestHandler):
    pass




httpd = HTTPServer((self.addressIP, self.port), MyHttpSimpleHandler)
print("Server started on " + self.addressIP + ",port " + str(self.port) + ".....")
httpd.serve_forever()

 

 

3. Draw UI and generate QR code

Written before

Pyqt+QRcode to generate recognition QR codes

Direct Reference Generation of 2D Codes

Draw UI

class MainWidgetUI(QDialog):
    def __init__(self, parent=None):
        super(MainWidgetUI, self).__init__(parent)
        self.setFixedSize(640, 480)  # PyQT Disable window resizing
        self.setWindowTitle('Python Create a local server environment to generate QR codes')
        self.setWindowIcon(QtGui.QIcon("favicon.ico"))
        # Main layout
        main_layout = QVBoxLayout()
        self.methodtype = QComboBox()
        self.methodTopLayout = QHBoxLayout()
        self.methodtype.addItem('file', QVariant(1))  # Use QVariant Preservation Key
        self.methodtype.addItem('address', QVariant(2))
        self.methodtype.setFixedWidth(90)  # Set fixed width to 90 px
        self.pushButton = QPushButton("Select File")
        self.Url = QLineEdit()
        self.Url.hide()
        self.methodTopLayout.addWidget(self.methodtype)  # Add a widget
        self.methodTopLayout.addWidget(self.Url)  # Add a widget
        self.methodTopLayout.addSpacing(10)  # Add a 10 px Spatial distance without elasticity
        self.methodTopLayout.addWidget(self.pushButton)
        self.qrcodeGroup = QVBoxLayout()
        self.groupBox = QGroupBox("QR code")
        self.QrLabel = QLabel(self.groupBox)

        self.qrcodeGroup.addWidget(self.groupBox)
        main_layout.addLayout(self.methodTopLayout)  # Add a layout
        main_layout.addLayout(self.qrcodeGroup)
        self.setLayout(main_layout)
        self.QrLabel.setGeometry(QRect(30, 30, 540, 380))  # Set up qrLabel Graphic Position
        # self.QrLabel.setScaledContents(True)  # Scale 2D code display

        self.pushButton.clicked.connect(self.FileOperator)  # Click the button
        self.methodtype.currentIndexChanged.connect(self.comboxchange)  # Events when drop-down box changes
        self.Url.textChanged.connect(self.comboxchange)  # Triggered when the contents of the address text box change

Generate two-dimensional code

# Get the server (address) to generate the QR code
    def ShowQrCode(self, strings):
        if not strings:  # The parameter is empty, pixmap Is empty
            self.QrLabel.setPixmap(QtGui.QPixmap(""))
        else:
            qr = qrcode.QRCode(version=None, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2, )
            qr.add_data(strings)
            qr.make(fit=True)
            img = qr.make_image()
            qraddr=tempDir+'qr.png'
            print(qraddr)
            img.save(qraddr)

 

Simply, by choosing the file get path, copy the file to the current directory, set the current directory to the http.server service directory, and use the QR code as the service address + file name

 

4. Matters needing attention

1. Get the current LAN IP

addressIP = socket.gethostbyname_ex(socket.gethostname())[-1][0]  # Get LAN IP

2. Get the temporary directory for windows

tempDir = tempfile.gettempdir() + '/'  # Get Temporary temp Catalog

3. copy file

There are two types of copy files, one that comes with Python and the other that comes with Pyqt

shutil.copy(filePath, "./")  # file=>Catalog
QFile.copy(filePath, sys.path[0]+"\\"+file)   #  QFile.copy Must file pair=>file

4. Use threads to open services

Opening httpd.serve_forever() directly in the UI can cause UI congestion, so use the QtCore.QThread thread to open the http service

5. Dynamically resize the UI

Different parameters result in different QR code sizes, so modify the UI size dynamically to display the entire QR code

qrsize = Image.open(qraddr).size
            if qrsize[0] > 400:  # Modify the size of the form dynamically when the 2-D code has a pixel value greater than 400
                dsize = qrsize[0] // 2  # Integer part
                self.setFixedSize(640 + dsize, 480 + dsize)
                self.QrLabel.setGeometry(QRect(30, 30, 540 + dsize, 380 + dsize))
            else:
                self.setFixedSize(640, 480)
                self.QrLabel.setGeometry(QRect(30, 30, 540, 380))
            self.QrLabel.setPixmap(QtGui.QPixmap(qraddr))

6. Determine if the file's md5 comparison file is the latest version

if filePath:
            file = filePath.split('/')[-1]
            isfExist = os.path.exists(file)
            if not isfExist:  # No file exists
                shutil.copy(filePath, "./")  # File pairs=>Catalog
            else:  # Files already exist, compare files md5 Determine whether it is the latest file
                md5FilePath = self.getFileMD5(filePath)
                md5File = self.getFileMD5(file)
                if md5File != md5FilePath:
                    shutil.copy(filePath,  "./")


    # Getting Files MD5 Value, for small files
    def getFileMD5(self, filepath):
        f = open(filepath, 'rb')
        md5obj = hashlib.md5()
        md5obj.update(f.read())
        hash = md5obj.hexdigest()
        f.close()
        return str(hash).upper()

7. Generate debug.log log log

def delog(string='--'):
    debugFile=open("debog.txt",'a',1,'utf-8')
    debugFile.writelines(string+'\n')
    debugFile.close()

 

5. Complete Code

# -*- coding: UTF8 -*-
import io, shutil, sys, os
from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import QtGui
import qrcode
from PIL import Image
import socket
import hashlib
import tempfile


port = 8080  # Default Port
addressIP = socket.gethostbyname_ex(socket.gethostname())[-1][0]  # Get LAN IP
tempDir = tempfile.gettempdir() + '/'  # Get Temporary temp Catalog


class MainWidgetUI(QDialog):
    def __init__(self, parent=None):
        super(MainWidgetUI, self).__init__(parent)
        self.setFixedSize(640, 480)  # PyQT Disable window resizing
        self.setWindowTitle('Python Create a local server environment to generate QR codes')
        self.setWindowIcon(QtGui.QIcon("favicon.ico"))
        # Main layout
        main_layout = QVBoxLayout()
        self.methodtype = QComboBox()
        self.methodTopLayout = QHBoxLayout()
        self.methodtype.addItem('file', QVariant(1))  # Use QVariant Preservation Key
        self.methodtype.addItem('address', QVariant(2))
        self.methodtype.setFixedWidth(90)  # Set fixed width to 90 px
        self.pushButton = QPushButton("Select File")
        self.Url = QLineEdit()
        self.Url.hide()
        self.methodTopLayout.addWidget(self.methodtype)  # Add a widget
        self.methodTopLayout.addWidget(self.Url)  # Add a widget
        self.methodTopLayout.addSpacing(10)  # Add a 10 px Spatial distance without elasticity
        self.methodTopLayout.addWidget(self.pushButton)
        self.qrcodeGroup = QVBoxLayout()
        self.groupBox = QGroupBox("QR code")
        self.QrLabel = QLabel(self.groupBox)

        self.qrcodeGroup.addWidget(self.groupBox)
        main_layout.addLayout(self.methodTopLayout)  # Add a layout
        main_layout.addLayout(self.qrcodeGroup)
        self.setLayout(main_layout)
        self.QrLabel.setGeometry(QRect(30, 30, 540, 380))  # Set up qrLabel Graphic Position
        # self.QrLabel.setScaledContents(True)  # Scale 2D code display

        self.pushButton.clicked.connect(self.FileOperator)  # Click the button
        self.methodtype.currentIndexChanged.connect(self.comboxchange)  # Events when drop-down box changes
        self.Url.textChanged.connect(self.comboxchange)  # Triggered when the contents of the address text box change

    # File Operation
    def FileOperator(self):
        filePath = self.selectFile()
        if filePath:
            file = filePath.split('/')[-1]
            isfExist = os.path.exists(file)
            if not isfExist:  # No file exists
                shutil.copy(filePath, "./")  # File pairs=>Catalog
                # delog(a)  #  Package exe debug log
                # QFile.copy(filePath, sys.path[0]+"\\"+file)  QFile.copy Must file pair=>file
            else:  # Files already exist, compare files md5 Determine whether it is the latest file
                md5FilePath = self.getFileMD5(filePath)
                md5File = self.getFileMD5(file)
                if md5File != md5FilePath:
                    shutil.copy(filePath,  "./")

            # Spliced 2D Code Parameters
            address = "http://" + addressIP + ':' + str(port) + '/' + file
            self.ShowQrCode(address)  # Display QR Code
            print('generate qrcord')
            self.Theading = TheadingPost((addressIP, port))  # Open process Open service-Direct Start http.service Causes UI Process not responding
            self.Theading.start()  # Thread Start



    # Getting Files MD5 Value, for small files
    def getFileMD5(self, filepath):
        f = open(filepath, 'rb')
        md5obj = hashlib.md5()
        md5obj.update(f.read())
        hash = md5obj.hexdigest()
        f.close()
        return str(hash).upper()

    # Select File
    def selectFile(self):
        # getOpenFileName  Only one can be selected    getOpenFileNames  Multiple choices
        files = QFileDialog.getOpenFileName(self, "Please select a playback file", '', "*.*")
        if files[0] == '':
            QMessageBox.warning(self, u'Error tip!', "Please select a file", QMessageBox.Yes)
        else:
            return files[0]

    # Drop-down box selection
    def comboxchange(self):
        currentIndex = self.methodtype.currentIndex()  # currentIndex  Index increases from 0
        key = self.methodtype.itemData(currentIndex)  # QVariant Saved key

        #  self.methodtype.currentText()  # text
        if key == 1:  # file
            self.pushButton.show()
            self.Url.hide()
            self.ShowQrCode("")
        elif key == 2:  # address
            self.pushButton.hide()
            self.Url.show()
            url = self.Url.text()
            self.ShowQrCode(url)

    # Get Server (Address) Generate QR Code 12
    def ShowQrCode(self, strings):
        if not strings:  # The parameter is empty, pixmap Is empty
            self.QrLabel.setPixmap(QtGui.QPixmap(""))
        else:
            qr = qrcode.QRCode(version=None, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2, )
            qr.add_data(strings)
            qr.make(fit=True)
            img = qr.make_image()
            qraddr=tempDir+'qr.png'
            print(qraddr)
            img.save(qraddr)
            qrsize = Image.open(qraddr).size
            if qrsize[0] > 400:  # Modify the size of the form dynamically when the 2-D code has a pixel value greater than 400
                dsize = qrsize[0] // 2  # Integer part
                self.setFixedSize(640 + dsize, 480 + dsize)
                self.QrLabel.setGeometry(QRect(30, 30, 540 + dsize, 380 + dsize))
            else:
                self.setFixedSize(640, 480)
                self.QrLabel.setGeometry(QRect(30, 30, 540, 380))
            self.QrLabel.setPixmap(QtGui.QPixmap(qraddr))


# return Html page
class MyHttpBaseHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print(self.path)
        enc = "UTF-8"
        encoded = ''.join(self.path).encode(enc)
        f = io.BytesIO()
        f.write(encoded)
        f.seek(0)
        self.send_response(200)
        self.send_header("Content-type", "text/html; charset=%s" % enc)
        self.send_header("Content-Length", str(len(encoded)))
        self.end_headers()
        shutil.copyfileobj(f, self.wfile)

    # This method serves the 'POST' request type, only allowed for CGI scripts.
    def do_POST(self):
        pass


# return  static  -m  eg:python -m http.server 8080
class MyHttpSimpleHandler(SimpleHTTPRequestHandler):
    pass


# Start Services
class TheadingPost(QThread):
    def __init__(self, list):
        super(TheadingPost, self).__init__()
        self.addressIP = list[0]
        self.port = list[1]

    def run(self):
        httpd = HTTPServer((self.addressIP, self.port), MyHttpSimpleHandler)
        print("Server started on " + self.addressIP + ",port " + str(self.port) + ".....")
        httpd.serve_forever()

def delog(string='--'):
    debugFile=open("debog.txt",'a',1,'utf-8')
    debugFile.writelines(string+'\n')
    debugFile.close()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_widget = MainWidgetUI()
    main_widget.show()
    sys.exit(app.exec_())

 

6. Operation results

Posted by vocoder on Sun, 19 Apr 2020 00:55:01 -0700