Python – Flask – abre una página web en el navegador predeterminado

Estoy trabajando en un pequeño proyecto en Python. Se divide en dos partes.

La primera parte es responsable de rastrear la web y extraer información e insertarla en una base de datos.

La segunda parte es responsable de presentar esa información con el uso de la base de datos. Ambas partes comparten la base de datos. En la segunda parte, estoy usando el marco de Flask para mostrar información como html con algún formato, estilo y etc. para que se vea más limpio.

Los archivos de origen de ambas partes están en el mismo paquete, pero para ejecutar este progtwig correctamente, el usuario debe ejecutar el rastreador y el presentador de resultados por separado de esta manera:

python crawler.py

y entonces

python presenter.py

Todo está bien, excepto una cosa. Lo que el presentador debe hacer es crear el resultado en formato html y abrir la página con los resultados en el navegador predeterminado del usuario, pero siempre se abre dos veces, probablemente debido a la presencia del método run (), que inicia Flask en un nuevo hilo y las cosas se nublan para mi No sé qué debo hacer para poder hacer que mi presenter.py abra solo una pestaña / ventana después de ejecutarlo.

Aquí está el fragmento de mi código:

from flask import Flask, render_template import os import sqlite3 # configuration DEBUG = True DATABASE = os.getcwd() + '/database/database.db' app = Flask(__name__) app.config.from_object(__name__) app.config.from_envvar('CRAWLER_SETTINGS', silent=True) def connect_db(): """Returns a new connection to the database.""" try: conn = sqlite3.connect(app.config['DATABASE']) return conn except sqlite3.Error: print 'Unable to connect to the database' return False @app.route('/') def show_entries(): u"""Loads pages information and emails from the database and inserts results into show_entires template. If there is a database problem returns error page. """ conn = connect_db() if conn: try: cur = connect_db().cursor() results = cur.execute('SELECT url, title, doctype, pagesize FROM pages') pages = [dict(url=row[0], title=row[1].encode('utf-8'), pageType=row[2], pageSize=row[3]) for row in results.fetchall()] results = cur.execute('SELECT url, email from emails') emails = {} for row in results.fetchall(): emails.setdefault(row[0], []).append(row[1]) return render_template('show_entries.html', pages=pages, emails=emails) except sqlite3.Error, e: print ' Exception message %s ' % e print 'Could not load data from the database!' return render_template('show_error_page.html') else: return render_template('show_error_page.html') if __name__ == '__main__': url = 'http://127.0.0.1:5000' webbrowser.open_new(url) app.run() 

Uso código similar en Mac OS X (con los navegadores Safari, Firefox y Chrome) todo el tiempo, y funciona bien. Suponiendo que puede estar ejecutando en la función de recarga automática de Flask. Establezca debug=False y no intentará recargarse automáticamente.

Otras sugerencias, basadas en mi experiencia:

  • Considere la posibilidad de aleatorizar el puerto que usa, ya que los bucles de edición de ejecución rápida a veces encuentran que el puerto 5000 del sistema operativo aún está en uso. (O, si ejecuta el código varias veces simultáneamente, por ejemplo, por accidente, el puerto todavía está en uso).
  • Permita que la aplicación gire brevemente antes de iniciar la solicitud del navegador. Lo hago a través de invocar threading.Timer .

Aquí está mi código:

 import random, threading, webbrowser port = 5000 + random.randint(0, 999) url = "http://127.0.0.1:{0}".format(port) threading.Timer(1.25, lambda: webbrowser.open(url) ).start() app.run(port=port, debug=False) 

(Todo esto está bajo la función if __name__ == '__main__': o en una función de “inicio de aplicación” separada si lo desea).