2012-06-20 78 views
8

Estoy trabajando en un pequeño proyecto en Python. Está dividido en dos partes.Python - Flask - abrir una página web en el navegador predeterminado

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 Flask framework para mostrar información como html con algunos formatos, estilos, 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 programa adecuadamente usuario tiene que ejecutar orugas y resulta presentador separado de esta manera:

pitón crawler.py

y luego

pitón presenter.py

Todo es simplemente allright, excepto una cosa. Lo que hago para presentar es 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 mí. No sé qué debería hacer para poder hacer que mi presentador.py abra solo una pestaña/ventana después de ejecutarlo.

Aquí es 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() 

Respuesta

17

utilizo un código similar en Mac OS X (con Safari, Firefox y los navegadores Chrome) todo el tiempo, y funciona muy bien. Supongo que es posible que te encuentres con la función de recarga automática de Flask. Establezca debug=False y no intentará volver a cargar automáticamente.

Otras sugerencias, basadas en mi experiencia:

  • Considere la aleatorización de puerto que utiliza, lo más rápido edit-gestión bucles de prueba a veces encontrar el puerto OS pensando 5000 todavía está en uso. (O bien, si ejecuta el código varias veces simultáneamente, digamos por accidente, el puerto realmente todavía está en uso).
  • Espere un momento la aplicación para que gire 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) 

(esto es bajo la if __name__ == '__main__':, o en una función separada "iniciar aplicación" si lo desea.)

+0

Gracias esto era útil. En realidad, bastaba con configurar la depuración en False ... y lo pasé tanto tiempo ... :) – koleS

+2

Derecha. 'debug = False' evita las ventanas duplicadas del navegador. El puerto aleatorizado y el retraso abierto son para corregir otros errores que he visto en diversas situaciones. –

+1

El problema de "dos ventanas de doble hoja" también se puede manejar (dejando 'debug = True') inspeccionando las variables de entorno. Cuando el script se vuelve a cargar a través de un cambio, la instancia recargada tiene configurada la variable de entorno 'WERKZEUG_RUN_MAIN'. Así que algo como: 'si 'WERKZEUG_RUN_MAIN' no está en os.environ: threading.Timer (BROWSER_DELAY, lambda: webbrowser.open (APP_URL)).start() 'lanzará (actualmente, al menos) el navegador una sola vez, independientemente de la configuración de depuración de la aplicación del matraz. – jedwards

Cuestiones relacionadas