Python

빅데이터 분석기사 실기 (Python)

과정 개요

빅데이터 분석기사 실기 시험을 완벽하게 대비하는 Python 기반 실전 과정입니다. 실제 시험 환경과 동일한 조건에서 데이터 분석, 모델링, 평가까지 전 과정을 학습합니다.

과정 정보

학습 목표

  • 빅데이터 분석기사 실기 시험의 3가지 유형 완벽 마스터
  • Python 라이브러리(Pandas, NumPy, Scikit-learn)를 활용한 데이터 분석

커리큘럼

1단계: 작업형 1유형 - 데이터 전처리

  • 데이터 읽기 및 탐색
  • 결측치 처리
  • 이상치 탐지 및 처리
  • 데이터 변환 및 인코딩
  • 그룹화 및 집계

2단계: 작업형 2유형 - 머신러닝 모델링

  • 분류 모델 (로지스틱 회귀, 의사결정나무, 랜덤포레스트 등)
  • 회귀 모델 (선형회귀, Ridge, Lasso 등)
  • 교차 검증 및 하이퍼파라미터 튜닝
  • 모델 평가 지표 (정확도, F1-score, ROC-AUC, RMSE 등)
  • 예측 결과 제출 형식

3단계: 작업형 3유형 - 통계 분석

  • 기술통계 분석
  • 가설 검정
  • 상관분석 및 회귀분석
  • 통계적 유의성 해석

실습 환경

  • 언어: Python

Logstash 실행 및 확인 - 기본예제

개요

  • Logstash 기본 설치 과정을 확인한다.
  • Logstash 활용 예제를 확인한다.

사전준비

  • 기존에 Elasticsearch와 Kibana 실행 방법을 알고 있어야 한다.
  • 모든 코드는 Windows 에서 실행하였다.

Logstash의 역할

  • 데이터 수집 (Ingest) - 데이터 변환 및 처리 (Processing / Filtering) - 데이터 출력 (Output)

데이터 수집

  • 다양한 데이터 소스로부터 데이터 수집
    • 로그파일
    • TCP/UDP/HTTP 요청
    • Kafka, Redis, JDBC(DB) 등

데이터 변환 및 처리 (Processing / Filtering)

  • 주요 내용

    • Logstash는 수집한 원시 데이터를 구조화된 형식으로 파싱하고 정제 및 가공
    • 정규표현식 기반 grok 필터로 로그 파싱
    • 날짜 포맷 통일 (date)
    • 필드 추가/삭제/이름 변경
    • 조건 분기 처리 (if, else)
    • JSON, CSV 파싱
    • 지오IP, 위치 정보 추가 등
  • 예시 코드

Elasticsearch - Transformers 임베딩 입력 저장 (Local Mode)

개요

  • 엘라스틱서치에서 밀집 벡터 위한 매핑 구성 방법 살펴보기
  • 밀집 벡터가 저장될 embedding 이라는 필드 정의
  • Python 코드로 엘라스틱서치 코드 구현

코드 전체 시나리오

  • Elasticsearch에 연결 및 인덱스 초기화
  • dense_vector 타입으로 매핑 정의
  • 문서 배열 정의
  • BERT 모델을 이용해 각 문서를 벡터 임베딩
  • 벡터 포함 문서를 Elasticsearch에 색인

Elasticsearch 클라이언트 연결

  • 로컬에서 실행 중인 Elasticsearch 서버에 접속
  • basic_auth: 로그인 자격 (ID: elastic, PW: 123456)
  • verify_certs=False: 인증서 검증 생략 (로컬에서 SSL 없이 사용 시 편의용)
es_admin = Elasticsearch("http://localhost:9200", 
                         basic_auth=("elastic", "123456"), 
                         verify_certs=False)

Mapping 정의 및 인덱스 생성

  • dense_vector: 벡터 검색용 필드 (벡터 유사도 기반 검색 가능)
  • dims: BERT의 출력 벡터는 기본적으로 768차원이므로 그에 맞춤
mapping = {
    "properties": {
        "embedding": {
            "type": "dense_vector",
            "dims": 768  # BERT의 출력 벡터 차원 수
        }
    }
}

기존 인덱스 삭제 후 새로 생성

  • 기존에 있던 chapter-2 인덱스를 삭제 (중복 방지)
  • 새로운 인덱스를 위에서 정의한 벡터 매핑으로 생성
try:
    es_admin.indices.delete(index="chapter-2")
    print("기존 chapter-2 인덱스를 삭제했습니다.")
except:
    print("chapter-2 인덱스가 존재하지 않습니다.")

es_admin.indices.create(index="chapter-2", body={'mappings': mapping})
print("새로운 chapter-2 인덱스를 생성했습니다.")

색인할 문서 데이터 구성

  • titletext로 구성된 단순 문서 리스트
  • text는 BERT 임베딩의 입력값이 된다
docs = [
    {"title": "Document 1", "text": "This is the first document"},
    {"title": "Document 2", "text": "This is the second document"},
    {"title": "Document 3", "text": "This is the third document"}
]

BERT 모델과 토크나이저 초기화

  • bert-base-uncased: Hugging Face에서 사전 학습된 BERT 모델
  • AutoTokenizer: 입력 텍스트를 BERT가 이해할 수 있는 토큰으로 변환
  • AutoModel: 텍스트에 대한 BERT 임베딩 추출
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")

BERT 임베딩 생성

  • tokenizer(...): 텍스트를 토큰화하고 PyTorch 텐서로 변환
  • model(**inputs): BERT 실행 → 각 토큰에 대한 임베딩 벡터 반환
  • last_hidden_state.mean(dim=1): 문장의 전체 임베딩을 mean pooling으로 하나의 벡터로 압축 (1×768 벡터)
  • squeeze(0).numpy(): 불필요한 batch 차원 제거 후 NumPy로 변환
  • tolist(): Elasticsearch에 저장 가능하게 리스트 형태로 변환
for doc in docs:
    text = doc["text"]
    inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True)
    with torch.no_grad():
        outputs = model(**inputs).last_hidden_state.mean(dim=1).squeeze(0).numpy() 
        doc["embedding"] = outputs.tolist()

Elasticsearch에 색인

  • 각 문서를 chapter-2 인덱스에 색인
  • Elasticsearch는 embedding 필드를 dense_vector로 저장하며, 향후 벡터 검색에도 사용 가능
for doc in docs:
    es_admin.index(index="chapter-2", body=doc)

확인

  • Kibana | Management | Dev Tools에서 색인된 문서 조회
GET chapter-2/_search

image.png

엘라스틱 클라우드에 데이터 추가하기 - 예제 (2025, 06)

CH03 - 데이터 추가

개요

  • Cloud에 데이터 추가

이전 예제 확인

파이썬 코드

# 필요한 라이브러리들을 가져옵니다
import time                    # 시간 지연을 위한 라이브러리
import requests               # HTTP 요청을 위한 라이브러리
from bs4 import BeautifulSoup # HTML 파싱을 위한 라이브러리
from elasticsearch import Elasticsearch  # Elasticsearch 클라이언트

# ✅ Elastic Cloud 연결 (API 키 인증 방식)
# Elastic Cloud의 클러스터에 API 키를 사용하여 연결합니다
# API 키는 사용자명/비밀번호 대신 더 안전한 인증 방식입니다
es = Elasticsearch(
    "your_cloud_url",  # Elastic Cloud 클러스터 URL
    api_key="your_api_key"  # API 키
)

# 저장할 인덱스 이름을 상수로 정의합니다
INDEX_NAME = "evan-elk-search"

# ✅ 인덱스 생성 (존재하지 않으면 새로 생성)
# Elasticsearch에서 데이터를 저장할 인덱스가 있는지 확인하고, 없으면 새로 생성합니다
if not es.indices.exists(index=INDEX_NAME):
    es.indices.create(index=INDEX_NAME)  # 새 인덱스 생성
    print(f"✅ Index '{INDEX_NAME}' created.")
else:
    print(f"✅ Index '{INDEX_NAME}' already exists.")

# ✅ 명언 수집 함수 정의
def get_quotes():
    """
    quotes.toscrape.com 웹사이트에서 명언들을 수집하는 함수
    
    Returns:
        list: 수집된 명언 요소들의 리스트 (BeautifulSoup 객체들)
    """
    res = requests.get("http://quotes.toscrape.com")  # 웹사이트에 GET 요청
    soup = BeautifulSoup(res.text, "html.parser")     # HTML을 파싱
    return soup.select(".quote")                       # .quote 클래스를 가진 요소들을 선택하여 반환

# ✅ 30초 간격으로 명언들을 하나씩 저장
# 수집된 명언들을 가져옵니다
quotes = get_quotes()

# 각 명언을 순회하면서 Elastic Cloud에 저장합니다
for i, q in enumerate(quotes):
    # 명언 데이터를 딕셔너리 형태로 구성합니다
    doc = {
        "text": q.select_one(".text").text.strip(),      # 명언 텍스트 추출 (공백 제거)
        "author": q.select_one(".author").text.strip(),  # 저자 이름 추출 (공백 제거)
        "tags": [tag.text for tag in q.select(".tag")]   # 태그들을 리스트로 추출
    }
    
    # Elastic Cloud에 문서를 저장합니다
    res = es.index(index=INDEX_NAME, document=doc)
    print(f"[{i+1}] ✅ Saved to Elastic Cloud: {res['_id']}")  # 저장된 문서의 ID 출력
    
    # 30초 대기 (다음 명언 저장 전)
    time.sleep(30)
  • 클라우드에서 확인

image.png

엘라스틱 서치 시작하기 - 예제 (2025, 06)

개요

  • 엘라스틱 클라우드 활용 예제 확인

회원가입

image.png

  • 가입 중간에 데이터 저장하는 공간이 있는데, 필자는 GCP를 선택하였다.

image.png

  • 다음 화면에서는 다음과 같이 지정하였다. General Purpose

image.png

  • 인덱스 명 : evan-elk-search

image.png

  • 인덱스 명을 확인하면 다음과 같다.
  • URL과 API 주소를 확인한다.
    • URL : your_url
    • your_api_key

image.png

설치 및 예제 확인

Windows 10

image.png

  • 압축 파일을 해제하고 C 드라이브쪽으로 폴더를 이동시킨다.

MSSQL Connect to Python (ver. 2025.04)

개요

  • SSMS에 계정 추가
  • 계정 추가 후 Python 라이브러리 활용해서 연동

계정 추가

  • 먼저 Security(보안) > Logins(로그인)에서 마우스 우클릭 진행
    • New Login 선택

image.png

  • 다음 화면에서 Loing Name은 evan-tester2 명명, Password는 1234로 지정함
    • Default Database는 BikeStores로 지정함
    • Enforce password policy 체크 박스 해제 (테스트용)

image.png

  • 왼쪽 메뉴에서 User Mapping 메뉴 선택
    • 하단 옵션에서 db_datawriter 옵션 선택

image.png

  • 왼쪽 메뉴에서 Server Roles 선택
    • dbcreator, public, sysadmin 선택
  • 선택이 완료되었다면 OK 버튼 클릭

image.png

Python 라이브러리 설치 확인

개요

  • requirements.txt 파일에 명시된 패키지들의 설치 여부와 버전을 확인하는 코드
  • 각 패키지에 대해 현재 환경에 설치된 버전을 출력하며, 설치되지 않은 경우 메시지 표시

예시

  • requirements.txt 파일에 다음과 같은 패키지가 있다고 가정한다.
  • 또한 가상 환경에 이미 아래 라이브러리가 설치가 되어 있다고 가정한다.
polars
pandas
numpy
matplotlib
seaborn
scikit-learn
graphviz
statsmodels
jupyterlab
pyarrow
deltalake
xlsx2csv
xlsxwriter
openpyxl
xlrd
  • 먼저 설치된 라이브러리 전체 개수를 확인한다.
import pkg_resources

# 현재 환경에 설치된 모든 패키지 목록과 버전 조회
installed_packages = [f"{dist.project_name}=={dist.version}" 
                     for dist in pkg_resources.working_set]
print(len(installed_packages))

[결과]
132
  • 이번에는 각 패키지에 대해 현재 환경에 설치된 버전을 출력하며, 설치되지 않은 경우 메시지 표시한다.
import pkg_resources

# requirements.txt 파일에 명시된 패키지들의 설치 여부와 버전을 확인하는 코드
# 각 패키지에 대해 현재 환경에 설치된 버전을 출력하며, 설치되지 않은 경우 메시지 표시
packages = [
    'polars', 'pandas', 'numpy', 'matplotlib', 'seaborn', 'scikit-learn', 'graphviz', 'statsmodels', 'jupyterlab', 'pyarrow', 'deltalake', 'xlsx2csv', 'xlsxwriter', 'openpyxl', 'xlrd'
]

# 각 패키지를 순회하면서 버전 정보 확인
for package in packages:
    try:
        # pkg_resources를 사용하여 설치된 패키지의 버전 정보 조회
        version = pkg_resources.get_distribution(package).version
        print(f"{package}: {version}")
    except pkg_resources.DistributionNotFound:
        # 패키지가 설치되지 않은 경우 예외 처리
        print(f"{package}: 설치되지 않음")
        
[결과]
polars: 1.22.0
pandas: 2.2.3
numpy: 2.0.2
matplotlib: 3.9.4
seaborn: 0.13.2
scikit-learn: 1.6.1
graphviz: 0.20.3
statsmodels: 0.14.4
jupyterlab: 4.3.5
pyarrow: 19.0.0
deltalake: 0.24.0
xlsx2csv: 0.8.4
xlsxwriter: 3.2.2
openpyxl: 3.1.5
xlrd: 2.0.1

Docker-Compose와 Dockerfile을 활용한 Flask-MySQL 연동 예제

개요

  • Docker-Compose와 Dockerfile의 주요 기능을 이해한다.
  • 각 파일의 위치와 주요 기능을 이해한다.

전체 프로젝트 파일 디렉터리

  • 본 프로젝트의 전체 코드는 다음과 같다.
  • 실제 코드 작성을 해야하는 곳은 다음과 같다.
    • app.py
    • requirements.txt
    • init.sql
    • docker-compose.yml
    • Dockerfile
docker_kubernetes_flask/
├── app/
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
├── db/
│   ├── init.sql
│   └── data/ (This will be created by Docker)
├── docker-compose.yml
└── Dockerfile

사전준비

  • 사전에 Docker는 Desktop 설치가 되어 있다고 가정한다.
  • 코드 편집을 위해서는 Visual Studio Code를 활용한다.

Docker가 익숙하지 않은 사람들을 위한 1줄 요약

  • MySQL 설치하고, Python 설치하고, 두개 또 연동해야 하고, CLI 명령어 또 각각 입력하는거 다 자동화 해줄게요!!
  • 즉, 자동화에 익숙해지자!

docker-compose와 Dockerfile 간단 비교

  • docker-compose.yml : python 컨테이너와 mysql 컨테이너를 각각 한꺼번에 구성하도록 스크립트를 작성함
  • Dockerfile : 여기에서는 python 개발환경을 구성함
  • docker-compose.yml에서 Dockerfile을 호출하여 개발환경을 만들도록 지시할 수 있음

전체 코드 흐름 1줄 요약

  • From MySQL to Python Flask

init.sql과 app.py 간단 설명

  • 각 두개의 파일은 사전에 미리 작성을 해둔다.

MySQL : init.sql

  • SQL 코드는 데이터베이스와 테이블을 생성하고, 테이블에 데이터를 삽입하는 작업을 수행.
    • test_db 데이터베이스 생성
    • users 테이블 생성
    • 간단하게 이름 생성
CREATE DATABASE IF NOT EXISTS test_db;

USE test_db;

CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

INSERT INTO users (name) VALUES ('Evan');
INSERT INTO users (name) VALUES ('Sara');
INSERT INTO users (name) VALUES ('Lotto');

Python : app.py

  • Python 코드는 Flask 웹 애플리케이션을 설정하여 MySQL 데이터베이스에 연결하고, 사용자 데이터를 JSON 형식으로 반환하는 작업을 수행.
from flask import Flask, jsonify
import mysql.connector
import os

app = Flask(__name__)

def get_db_connection():
    connection = mysql.connector.connect(
        host='mysql',
        user='root',
        password='example',
        database='test_db'
    )
    return connection

@app.route('/')
def index():
    connection = get_db_connection()
    cursor = connection.cursor()
    cursor.execute('SELECT * FROM users')
    users = cursor.fetchall()
    cursor.close()
    connection.close()
    users_list = [{"id": user[0], "name": user[1]} for user in users]
    return jsonify(users_list)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
  • 좀더 구체적으로 살펴본다.

step 01 - 라이브러리 불러오기

  • Flask: Flask 웹 애플리케이션 프레임워크를 불러오기
  • jsonify: 데이터를 JSON 형식으로 변환하여 HTTP 응답으로 반환하는 데 사용
  • mysql.connector: MySQL 데이터베이스에 연결하기 위해 사용
from flask import Flask, jsonify
import mysql.connector
import os

step 02 - Flask Application Setup

  • Flask 애플리케이션 인스턴스를 생성. __name__은 현재 모듈의 이름을 전달하여 Flask 애플리케이션을 생성하는 데 사용.
app = Flask(__name__)

step 03 - Database Connection Function

  • get_db_connection 함수는 MySQL 데이터베이스에 연결하고, 연결 객체를 반환.
  • host, user, password, database 매개변수는 데이터베이스에 연결하기 위한 정보
def get_db_connection():
    connection = mysql.connector.connect(
        host='mysql',
        user='root',
        password='example',
        database='test_db'
    )
    return connection

step 04 - Index Route

  • @app.route('/'): 해당 Decorator는 URL (’/’)에 대한 요청을 처리하는 index 함수를 정의.
  • index 함수의 내용은 다음과 같이 구성됨
    • get_db_connection을 호출하여 데이터베이스에 연결.
    • 연결 객체에서 커서를 생성하고, SELECT * FROM users 쿼리를 실행하여 users 테이블의 모든 데이터를 가져오기
    • 데이터를 가져온 후 커서와 연결을 닫기
    • users 데이터를 List Comprehension을 사용하여 딕셔너리 형태로 변환합니다. 각 사용자에 대해 idname 키를 가지는 딕셔너리를 생성.
      • 이 부분은 별도의 HTML 소스코드를 넣지 않기 위해서 진행한 것이니, 해당 자세한 내용을 보기를 원한다면 Flask 웹개발로 더 공부할 것 권장
    • 변환된 리스트를 jsonify를 사용하여 JSON 형식으로 반환.
@app.route('/')
def index():
    connection = get_db_connection()
    cursor = connection.cursor()
    cursor.execute('SELECT * FROM users')
    users = cursor.fetchall()
    cursor.close()
    connection.close()
    users_list = [{"id": user[0], "name": user[1]} for user in users]
    return jsonify(users_list)

step 05 - Running the Application

  • 모듈이 직접 실행될 때만 Flask 애플리케이션을 실행
    • app.run 메소드를 호출하여 애플리케이션을 시작.
    • host='0.0.0.0': 애플리케이션이 모든 네트워크 인터페이스에서 접근 가능하도록 설정.
    • port=5000: 애플리케이션이 5000번 포트에서 실행되도록 설정.
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Python : requirements.txt

  • 주요 라이브러리 설치 위해 필요한 라이브러리 2개만 설치
  • 추후에 독자가 라이브러리 추가 가능
Flask
mysql-connector-python

Docker: Dockerfile

  • Dockerfile은 Python 애플리케이션을 컨테이너화하기 위한 스크립트
  • 다른 파일과 달리 확장자명이 없다는 것에 주의
  • 다양한 옵션에 대해 설명하도록 한다.
FROM python:3.10-slim

WORKDIR /app

COPY app/requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY app/ .

EXPOSE 5000

CMD ["python", "app.py"]

step 01 - FROM

FROM python:3.10-slim
  • Base Image를 선택한다. 해당 이미지를 선택하려면 Docker Hub 검색창에서 확인 (Login 필수)
  • 각 Base Image를 선택하면 관련 Tag가 존재하며 여기에서 Tags 확인해서 입력하도록 한다.
  • Docker Official Image 를 선택한다.

Screenshot 2024-07-01 at 8.16.09 AM.png

Streamlit on Google Colab

개요

  • 개발환경설정이 어려운 환경에서 Google Colab 상에서 Streamlit 설치 및 실행을 익히고자 한다.
  • 주로 강의 목적으로 사용하기를 바란다.

Streamlit 라이브러리 설치

  • 아래 코드를 활용하여 streamlit 라이브러리 설치
!pip install -q streamlit

Untitled

Streamlit 코드 작성 샘플

%%writefile app.py

import streamlit as st
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import seaborn as sns

@st.cache_data
def load_data():
    df = sns.load_dataset('tips')
    return df

def main():
    st.title("Streamlit with Plotly")   
    tips = load_data()

    # 데이터가공
    m_tips = tips.loc[tips['sex'] == 'Male', :]
    f_tips = tips.loc[tips['sex'] == 'Female', :]

    # 시각화 차트
    fig = make_subplots(rows = 1,
                        cols = 2,
                        subplot_titles=('Male', 'Female'),
                        shared_yaxes=True,
                        shared_xaxes=True,
                        x_title='Total Bill($)'
                        )
    fig.add_trace(go.Scatter(x = m_tips['total_bill'], y = m_tips['tip'], mode='markers'), row=1, col=1)
    fig.add_trace(go.Scatter(x = f_tips['total_bill'], y = f_tips['tip'], mode='markers'), row=1, col=2)
    fig.update_yaxes(title_text="Tip($)", row=1, col=1)
    fig.update_xaxes(range=[0, 60])
    fig.update_layout(showlegend=False)
    
    # 중요포인트
    # fig.show()
    st.plotly_chart(fig, use_container_width=True)

if __name__ == "__main__":
    main()

Untitled

django-web on GCE

개요

  • django-web을 GCE에 설치 및 배포를 간단하게 진행하도록 한다.

사전준비

  • Google Cloud Platform 회원가입은 미리 진행했고, GCE 인스턴스를 생성할 줄 아는 상태임을 전제로 한다.
  • Miniconda 설치가 끝난 상황임을 가정한다.
  • Miniconda 설치
mkdir -p ~/miniconda3
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
rm -rf ~/miniconda3/miniconda.sh
  • 설치 후, 새로 설치한 미니콘다를 초기화합니다. 다음 명령은 bash 및 zsh 셸을 초기화
~/miniconda3/bin/conda init bash
~/miniconda3/bin/conda init zsh

django on GCE

  • GCE Shell에서 django를 설치한다.
pip install django
  • django의 버전을 확인한다.
django-admin --version
5.0.4
  • project 명령어를 입력한다.
django-admin startproject mysite
  • 서버를 실행해본다.
    • 경로를 mysite에 이동 시킨 후 아래 명령어를 실행한다.
$ python manage.py makemigrations
$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK
$ python manage.py runserver
...

April 18, 2024 - 05:13:47
Django version 5.0.4, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Untitled