Forums

Errno98 Address already in use (Flask)

My aim is to have a QR scanner that can take the data and check it against a list of names and emails in a Google Sheet, modifying a 'Signed In' column if necessary, and telling the user the result. (Either: Successfully signed in; Already signed in; or Not on the list.) For now, in place of the scanner, I've just got a html form where I can type in some example data to test the system out. If I get that working I can worry about the camera/QR stuff later.

I've put the code of two files below. 'flask_app.py' is what the user will see. 'UpdateSheet.py' deals with reading/changing the Google Sheet (I've tested this on its own in pythonanywhere and it works), and returns a value 1, 2, or 3 to flask_app.py depending on what's happened. I used this tutorial as my starting point and changed things around according to what I need.

Here's flask_app.py:

from flask import Flask, request
from UpdateSheet import Compare

app = Flask(__name__)
app.config["DEBUG"] = True

@app.route("/", methods=["GET", "POST"])
def adder_page():
    if request.method == "POST":
        QR_Data = request.form["QRData"]
        result = Compare(QR_Data)
        if result == 1:
            return '''
                <html>
                    <body>
                        <p>Successfully signed in.</p>
                        <p><a href="/">Click here to scan another QR Code.</a></p>
                    </body>
                </html>
                '''
        elif result == 2:
            return '''
                <html>
                    <body>
                        <p>This person has already signed in.</p>
                        <p><a href="/">Click here to scan another QR Code.</a></p>
                    </body>
                </html>
            '''
        elif result == 3:
            return '''
                <html>
                    <body>
                        <p>This person cannot be signed in: they have not completed the induction.</p>
                        <p><a href="/">Click here to scan another QR Code.</a></p>
                    </body>
                </html>
            '''

    return '''
        <html>
            <body>

                <form method="post" action=".">
                    <p><input name="QRData" />QR Code Data:</p>
                    <p><input type="submit" value="Sign In" /></p>
                </form>
            </body>
        </html>
        '''

And here's UpdateSheet.py:

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

# The ID and range of the spreadsheet.
Inductees = '1n1pTDsh3q5zPWxQLsewQ-3YBgyXKsx_t9LniZEZCDh8'
NamesAndEmails = 'Sheet1!A2:C'

SignedIn = 0 # 1=successful, 2=already signed in, 3=not done induction


creds = None

if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)

if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            '/home/willsygma/mysite/credentials.json', SCOPES)
        creds = flow.run_local_server()

        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

service = build('sheets', 'v4', credentials=creds)

# Call the Sheets API
sheet = service.spreadsheets()
result = sheet.values().get(spreadsheetId=Inductees,
                            range=NamesAndEmails).execute()
values = result.get('values', [])

def Compare(values, DataInput):
    DataInput = ""
    ScannedName = []
    ScannedEmail = ""

    DataInput = DataInput.replace('+', ' ')
    for word in DataInput.split():
        if '@' in word:
            ScannedEmail = word
        else:
            ScannedName.append(word)
    ScannedName = ' '.join(ScannedName) # converts list to a string

    if not values: # If the sheet is blank
        SignedIn = 3
    else:

        counter = 1
        Matched = False
        for Row in values:
            counter+=1
            if ScannedName == Row[0] and ScannedEmail == Row[1]: # a match
                Matched = True
                SignIn(Row, ScannedName, counter)
        if Matched == False:
            SignedIn = 3
    return SignedIn

def SignIn(Row, Name, counter):
    if Row[2] == 'Y': # if they have already signed in
        SignedIn = 2
    else:             # if the Signed In column already reads 'Y'
        SignedIn = 1
        body = {'values': [["Y"]]}
        sheet.values().update(
                spreadsheetId=Inductees, range="C" + str(counter),
                valueInputOption="RAW", body=body).execute() # Signs in
    return SignedIn

The webpage is a 'Something went wrong :-(' message with Error Code: Unhandled Exception.

This is what I get in the error log:

2019-02-12 13:58:14,527: Error running WSGI application
2019-02-12 13:58:14,533: OSError: [Errno 98] Address already in use
2019-02-12 13:58:14,533:   File "/var/www/willsygma_pythonanywhere_com_wsgi.py", line 16, in <module>
2019-02-12 13:58:14,533:     from flask_app import app as application  # noqa
2019-02-12 13:58:14,533: 
2019-02-12 13:58:14,534:   File "/home/willsygma/mysite/flask_app.py", line 2, in <module>
2019-02-12 13:58:14,534:     from UpdateSheet import Compare
2019-02-12 13:58:14,534: 
2019-02-12 13:58:14,534:   File "/home/willsygma/mysite/UpdateSheet.py", line 30, in <module>
2019-02-12 13:58:14,534:     creds = flow.run_local_server()
2019-02-12 13:58:14,534: 
2019-02-12 13:58:14,534:   File "/home/willsygma/.local/lib/python3.7/site-packages/google_auth_oauthlib/flow.py", line 407, in run_local_server
2019-02-12 13:58:14,535:     host, port, wsgi_app, handler_class=_WSGIRequestHandler)
2019-02-12 13:58:14,535: 
2019-02-12 13:58:14,535:   File "/usr/lib/python3.7/wsgiref/simple_server.py", line 153, in make_server
2019-02-12 13:58:14,535:     server = server_class((host, port), handler_class)
2019-02-12 13:58:14,535: 
2019-02-12 13:58:14,535:   File "/usr/lib/python3.7/socketserver.py", line 449, in __init__
2019-02-12 13:58:14,535:     self.server_bind()
2019-02-12 13:58:14,536: 
2019-02-12 13:58:14,536:   File "/usr/lib/python3.7/wsgiref/simple_server.py", line 50, in server_bind
2019-02-12 13:58:14,536:     HTTPServer.server_bind(self)
2019-02-12 13:58:14,536: 
2019-02-12 13:58:14,536:   File "/usr/lib/python3.7/http/server.py", line 137, in server_bind
2019-02-12 13:58:14,537:     socketserver.TCPServer.server_bind(self)
2019-02-12 13:58:14,537: 
2019-02-12 13:58:14,537:   File "/usr/lib/python3.7/socketserver.py", line 463, in server_bind
2019-02-12 13:58:14,537:     self.socket.bind(self.server_address)

I don't expect to get this working but where might I start?

NB: I've been learning Python for an embarrassing length of time with no success. I have the wrong brain for it. Basically I'm a desperate office administrator out of my depth. I've seen other threads on this error message but I am several years away from understand the answers. However I'm pretty sure they don't apply to my project. Please explain anything like you're talking to a computer-illiterate 6-year-old. Alternatively, if I should stop trying, please don't hesitate to tell me. Thanks in advance.

Your UpdateSheet module seems to be trying to start it's own server (at line 30). That's not going to work. You'll have to check your code to see whether it's necessary to start your own server there or if there's some way that you can accomplish what you're trying to do without starting another server there.

Thanks very much for your advice Glenn. I don't really understand what this means or what it entails me changing, but I'll try to work it out.