MmmHmm
MmmHmm

Reputation: 3785

Exiting Flask server raises "OSError: [Errno 9] Bad file descriptor" when app.run(debug=True)

Is this just part of the debugging process with Flask? Is this because the Flask server is reading into a file that it is writing to? Am I not closing connections properly?

From what I can gather errno(9) indicates:

(bad file number), when the file descriptor you are using is not valid. Either the file descriptor refers to no open file, or a read (or write) request is made to a file that is open only for writing (or reading). If you are doing socket programming, the socket descriptor has got closed before you could do any operation on that and you may end up with this error.

I am using Virtualenv 15.1.0, Python 3.6.0 and Flask 0.12 &

$  pip freeze
appdirs==1.4.2
click==6.7
Flask==0.12
itsdangerous==0.24
Jinja2==2.9.5
MarkupSafe==0.23
packaging==16.8
pyparsing==2.1.10
requests==2.13.0
six==1.10.0
Werkzeug==0.11.15

This is the code I am writing which invokes the error upon exiting the server:

from flask import Flask, render_template, request, jsonify
import sqlite3
app = Flask(__name__)

connection = sqlite3.connect('database.db')
connection.execute('CREATE TABLE IF NOT EXISTS films (title TEXT, rating INTEGER)')
connection.close()      <------------------ IMPROPER CLOSURE?

@app.route('/')
def index():
    return render_template("base.html")

@app.route('/movie', methods = ['POST'])
def add_movie_function():
    connection  = sqlite3.connect('database.db')
    cursor      = connection.cursor()
    title       = request.form['title']
    rating      = request.form['rating']
    try:
        query   = 'INSERT INTO films (title, rating) VALUES (?, ?)'
        cursor.execute(query, (title, rating))
        connection.commit()
        message = 'Successfully inserted title and rating data into movies table!'
    except:
        connection.rollback()
        message = 'There was an issue with inserting data into the movies table :('
    finally:
        connection.close() <------------------ IMPROPER CLOSURE?
        return message

@app.route('/movies', methods = ['GET'])
def list_all_movies():
    connection = sqlite3.connect('database.db')
    cursor = connection.cursor()
    try:
        cursor.execute('SELECT * FROM films')
        connection.commit()
        search_result = jsonify(cursor.fetchall())
    except:
        search_result = 'An error occured getting all the film titles'
    finally:
        connection.close() <------------------ IMPROPER CLOSURE?
        return search_result

app.run(debug = True)

...and this is the full traceback:

(venv) 66 Wed Mar 08 15:29:11$  export FLASK_APP=simpleFlaskAPI.py 
(venv) 67 Wed Mar 08 15:42:08$  flask run
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 230-157-201
127.0.0.1 - - [08/Mar/2017 15:42:21] "GET /movies HTTP/1.1" 200 -
^C * Serving Flask app "simpleFlaskAPI"
Traceback (most recent call last):
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/bin/flask", line 11, in <module>
    sys.exit(main())
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/flask/cli.py", line 507, in main
    cli.main(args=args, prog_name=name)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/flask/cli.py", line 374, in main
    return AppGroup.main(self, *args, **kwargs)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args[1:], **kwargs)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/flask/cli.py", line 432, in run_command
    use_debugger=debugger, threaded=with_threads)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/werkzeug/serving.py", line 708, in run_simple
    inner()
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/werkzeug/serving.py", line 670, in inner
    fd=fd)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/werkzeug/serving.py", line 564, in make_server
    passthrough_errors, ssl_context, fd=fd)
  File "/Users/username/python/lesson4/python-minicamp-homework-4/venv/lib/python3.6/site-packages/werkzeug/serving.py", line 474, in __init__
    socket.SOCK_STREAM)
  File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 460, in fromfd
    nfd = dup(fd)
OSError: [Errno 9] Bad file descriptor

If this is abnormal, should I file a bug report with the folks of Flask?

Thank you!


UPDATE per Pipskweak's suggestions, I have modified the script:

from flask import Flask, render_template, request, jsonify
import sqlite3

app = Flask(__name__)

connection = sqlite3.connect('database.db')
connection.execute('CREATE TABLE IF NOT EXISTS films (title TEXT, rating INTEGER)')
connection.close()

@app.route('/')
def index():
    return render_template("base.html")

@app.route('/movie', methods = ['POST'])
def add_movie_function():
    data = None
    try:
        connection  = sqlite3.connect('database.db')
        with connection:
            cursor      = connection.cursor()
            title       = request.form['title']
            rating      = request.form['rating']
            query   = 'INSERT INTO films (title, rating) VALUES (?, ?)'
            data = cursor.execute(query, (title, rating))
            connection.commit()
            message = 'Successfully inserted title and rating data into movies table!'
    except sqlite3.Error as e:
        if connection:
            connection.rollback()
            message = 'There was an issue with inserting data into the movies table :('
        raise ValueError('sqlite3: {}'.format(e))
    finally:
        if connection:
            connection.close()
            print(message)
        if data:
            print(data)
            return message

@app.route('/movies', methods = ['GET'])
def list_all_movies():
    data = None
    try:
        connection = sqlite3.connect('database.db')
        with connection:
            cursor = connection.cursor()
            data = cursor.execute('SELECT * FROM films')
            connection.commit()
            search_result = jsonify(cursor.fetchall())
    except sqlite3.Error as e:
        if connection:
            search_result = 'An error occured getting all the film titles'
        raise ValueError('sqlite3: {}'.format(e))
    finally:
        if connection:
            connection.close()
            print(search_result)
        if data:
            print(data)
            return search_result

app.run(debug = True)
# if __name__ == '__main__':
#     print('__name__ == "__main__"')
#     app.run(debug = True)

OF NOTE: using the if __name_ == ... does not invoke debugger mode in Flask when invoking flask by export FLASK_APP... and flask run. Using python3 scriptname.py with the if name == main, however, does invoke debugger - so I suspect something is amiss with Flask here?

AND I also adjusted the script to run in python 2 (only a couple print statements and the except sqlite3.Error, e: syntax) and tried running it in Flask (using debugger mode) using virtual environment and the python script works fine with the html and when I quit out of the Flask server, no OSError: [Errno 9] Bad file descriptor. So, is this a bug I should report to the Flask folks?

FWIW:

$  pip freeze  
appdirs==1.4.3  
click==6.7  
Flask==0.12  
itsdangerous==0.24  
Jinja2==2.9.5  
MarkupSafe==1.0  
packaging==16.8  
pyparsing==2.2.0  
requests==2.13.0  
six==1.10.0  
Werkzeug==0.11.15

Perhaps this is a similar issue?

Upvotes: 1

Views: 3800

Answers (1)

user5201343
user5201343

Reputation:

So, the try, except, finally statement might be causing some issues.

Did you want to give this a shot? It's a little more specific on the exceptions and closing the connection.

def query_db(sql_statement):
    try:
        # connect to database
        conn = sqlite3.connect('database.db')
        with conn:
            cur = conn.cursor()
            data = cur.execute(sql_statement)
            # commit the changes
            conn.commit()

    except sqlite3.Error, e:
        # if an error has occured, rollback the changes
        if conn:
            conn.rollback()

        # print the error out. Probably useful.
        raise ValueError('sqlite3: {}'.format(e))

    finally:
        # lastly, close the database, probably a good idea.
        if conn:
            conn.close()
        if data:
            return data

Also, your missing the if statement before app.run()

if __name__ == "__main__":
    app.run(debug=True)

Upvotes: 1

Related Questions