skip to Main Content

I am working on a pytho app and below is the flask controller where an endpoint is exposed and triggering another script once received request.

import subprocess
from flask import Flask, request, jsonify
import os
from dotenv import load_dotenv
import requests
import json
from requests.auth import HTTPBasicAuth

load_dotenv()
app = Flask(__name__)

environment = os.environ.get('ENVIRONMENT', 'dev')
valid_client = os.environ.get('VALID_CLIENT')

# Load environment-specific configuration from config file
config_file_name = f'config/config_{environment}.json'
client_id = os.environ.get('CLIENT_ID')
client_secret = os.environ.get('CLIENT_SECRET')

try:
    with open(config_file_name, 'r') as config_file:
        config = json.load(config_file)
except FileNotFoundError:
    print(f"Config file '{config_file_name}' not found. Please make sure the file exists.")
    exit(1)  # Exit the program with an error code



@app.before_request
def authorize_request():
    auth_header = request.headers.get("Authorization")
    if auth_header is None or not auth_header.startswith("Bearer "):
        return jsonify({"message": "Missing or invalid token"}), 401

    # Extract the token
    bearer_token = auth_header.split(" ")[1]

    auth = HTTPBasicAuth(client_id, client_secret)
    headers = {
        "Content-Type": "application/json",
        "Accept": "application/json"
    }

    # Construct the request body
    data = {
        "access_token": bearer_token
    }

    # Make the POST request with authentication and token in the body
    response = requests.post(config['token_validation_url'], auth=auth, headers=headers, json=data)

    if response.status_code == 200:
        response_data = response.json()
        if response_data.get("Status") == "INVALID" or not response_data.get("UserId").endswith(valid_client):
            return jsonify({"message": "Token validation failed"}), 401

    

@app.route('/process-csv', methods=['POST'])
def process_csv():
    try:
        file = request.files['file']

        if file and file.filename.endswith('.csv'):
            # Save the uploaded CSV file to a temporary location
            csv_file_path = f'/tmp/{file.filename}'
            file.save(csv_file_path)

            subprocess.Popen(['python3', 'publisher.py', csv_file_path])

            return jsonify({'message': 'CSV file uploaded and processing started in the background'})

        
        return jsonify({'message': 'Invalid file format. Please upload a CSV file.'}), 400
    except Exception as e:
        return jsonify({'message': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

App Structure:

enter image description here

As of now to deploy the app I am copying the scripts and installing the dependences on the prod linux server and starting up the controller with python3 controller.py.

Sometimes I am facing issue related to different environment or python version (as compare to local development environment) and managing it’s dependencies on the prod server and had to resolve them manually.

what is the recommended way to deploy the python app ? shall I containerize this app ? Please suggest.

2

Answers


  1. The way I do it is I get a free google cloud VM:

    https://many.pw/hosting

    "e2-micro" VM. You get a 30GB hard drive, 1GB ram, and two AMD EPYC 7B12 2250 MHz processors. That’s enough to run a nice little site with plenty of traffic.

    And I put the very latest version of Ubuntu 22.04.3 LTS (Jammy Jellyfish) which comes with a nice recent version of python.

    Then I just clone the python repo on the server and use systemd to run uvicorn:

    [Unit]
    Description=python
    After=network.target network-online.target
    Requires=network-online.target
    
    [Service]
    User=andrew
    Group=andrew
    EnvironmentFile=/etc/systemd/system/aa-service.conf
    ExecStart=uvicorn main:app --reload
    Restart=on-failure
    RestartSec=1s
    
    [Install]
    WantedBy=multi-user.target
    
    Login or Signup to reply.
  2. There are several ways to run python app on the production server.

    First of all, flask used development server by default. For production you can use uWSGI or gunicorn or other wsgi server.

    1. The first way is to configurate flaskapp + wsgi server manualy
    2. The second way is to use docker

    I recomended tiangolo/uwsgi-nginx-flask this docker image, because it’s easy to use with flask apps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search