docker나 기타 리눅스 서버로 서버를 실행하면 로그를 살펴보거나 기타 모니터링 하기 편리합니다.

하지만 iis에서 flask 서버를 서비스하면 기본적인 debug 로그도 살펴보기가 매우 어렵습니다.

 

anaconda3 환경에서 iis에 flask 서비스를 설정해둔 상태여서 기본적은 에러조차 로그로 파악하기가 어렵습니다

불친절한 IIS 서버

local 상에서 정상작동하는 서버인데 iis에서만 위와같은 500에러만 나오는 상태, 맨 윗줄부터 디버깅을 하다가 작성한 코드입니다.

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def check_packages():
    packages = [
        'flask', 'watchdog', 'pysftp', 'PIL', 'psycopg2', 'requests'
    ]

    package_status = {}
    for package_name in packages:
        try:
            __import__(package_name)
            package_status[package_name] = 'Installed'
        except ImportError:
            package_status[package_name] = 'Not Installed'

    return render_template('packages.html', package_status=package_status)

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

 

templates/packages.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Package Status</title>
</head>
<body>
    <h1>Package Status</h1>
    <table border="1">
        <tr>
            <th>Package Name</th>
            <th>Status</th>
        </tr>
        {% for package_name, status in package_status.items() %}
        <tr>
            <td>{{ package_name }}</td>
            <td>{{ status }}</td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

 

dataframe의 한 컬럼에 대해 unique한 값을 얻기위해 'datafame['컬럼명'].uique()' 메소드를 사용할 수 있고 결과값이 list가 아닌 ndarray형태로 생성돼죠.

 

unique() 메소드를 이용하여 생성된 list를 다른 컬럼으로 생성하거나 비교를 위한 list로 활용하려하던 중 ndarray 형태로는 원하는 작업에 지장이 생겨서 list형태로 변환하는 과정입니다.

 

numpy 형태의 배열의 경우 list와 다르게 ','로 구분이 안되어있습니다.

list형태로 간단하게 변경할 수 있습니다.

import numpy as np
unique_values = df_proceed['시간대별'].unique()
print(unique_values)
print(type(unique_values))

# ndarray to list
python_list = unique_values.tolist()
# 결과 확인
print(python_list)

ndarray

 flask로 간단한 웹 페이지를 만들어서 Local 환경에서 테스트한 후, 서버에 docker container로 서비스를 가동하니 접속이 안되는 문제가 발생하였습니다.

if __name__ == '__main__':
    cache.clear()
    app.run(debug=True, port=8888)

1. port binding도 잘 해주었고,

2. host도 오타없이 잘 작성하였고,

3. python 파일도 정상적으로 실행되고 있었습니다.

 


host='0.0.0.0'

해결책은 간단했습니다.

 

Flask 애플리케이션을 실행할 때, Flask 서버는 기본적으로 127.0.0.1 또는 localhost에서만 연결을 허용합니다.

따라서 "Running on http://127.0.0.1:8888"과 같이 로컬 주소에서만 서버가 실행되는 것이 기본 동작입니다.

하지만 "Running on all addresses (0.0.0.0)" 또는 "Running on http://172.17.0.2:8100"와 같이 모든 주소에서 서버를 실행하려면 Flask 애플리케이션을 아래와와 같은 코드로 실행해야합니다.

if __name__ == '__main__':
    cache.clear()
    app.run(debug=True, host='0.0.0.0', port=8888)

바로 run()함수에 'host = '0.0.0.0'으로 지정해두니 서버 호스트로도 접속이 정상적으로 이루어졌습니다.

 

아래는 chat-gpt가 답해준 내용입니다. 훌륭한 설명이네요.

이렇게 하면 Flask 서버가 모든 주소 (0.0.0.0)에서 클라이언트 연결을 허용하며, 외부 클라이언트도 액세스할 수 있게 됩니다. 
단, 이렇게 서버를 열면 보안상 주의가 필요하며, 특히 개발 환경에서만 사용해야 합니다. 
production(운영) 환경에서는 보안 검토와 관련된 설정을 고려해야 합니다.
따라서 Flask 애플리케이션을 모든 주소에서 실행하고 싶다면 위의 코드를 Flask 애플리케이션 코드 안에서 사용하십시오.

 

python flask로 구현한 웹 페이지를 가상화공간(docker container)에서 서비스하려할 때 위와 같은 문제가 발생하시는 분들께 도움이 되었으면 합니다.

 

* 참고 : pytutbe 모듈은 python 3.6 버전 이상에서 작동합니다!

 

 유튜브 영상을 다운로드 받는 방법은 여러가지지만 써드파티 유틸리티를 다운받거나 사용하려니 번거로움이 있어서 파이썬으로 간단하게 구현해봤습니다.

 유튜브 플레이리스트에 있는 영상도 한 번에 다운로드 할 수 있게 구현한 코드이니 주석 참고해주시고 궁금하신 점은 무엇이든 남겨주세요 ㅎ


프로그램 순서는 대략적으로 아래와 같습니다.

1. 다운로드 받을 유튜브 플레이리스트 URL을 리스트로 생성해줌

2. 유튜브 플레이리스트 제목을 이름으로 갖는 폴더를 생성함

3. 생성한 폴더 안에 유튜브 플레이리스트 안에 있는 모든 영상을 다운로드 해줌

from pytube import YouTube
from pytube import Playlist
import os

# 참고 1) 폴더 생성 : https://data-make.tistory.com/170
# '폴더명'을 매개변수로 받는 함수, 파라미터로 받은 폴더명과 같은 폴더가 없으면 폴더를 새로 생성해줌
def createFolder(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
        print ('Error: Creating directory. ' +  directory)


# 참고 2) pytube 기본 사용법 :  https://pytube.io/en/latest/user/playlist.html
# '플레이리스트 URL'을 매개변수로 받는 함수
def playlist_download(playlist_url):
    # 플레이리스트 제목을 폴더명으로 사용하여 폴더를 생성할 것 -> 플레이리스트 이름 가져오기
    p = Playlist(playlist_url)
    
    ############################################################################
    # 참고) 아래 방법으로 간다하게 구현할 수 있으나 고해상도 영상을 다운받을 수 없음!!    
    # for video in p.videos:
    #     video.streams.first().download(DOWNLOAD_FOLDER)
    ############################################################################
    
    print(p.title)
    DOWNLOAD_FOLDER = p.title
    
    # 플레이리스트 제목으로 폴더 생성
    createFolder(DOWNLOAD_FOLDER)

    # 플레이리스트 안의 각 영상마다 URL을 가져온 후 지정한한 경로에 다운로드를 해줌
    for url in p.video_urls:
        print(url)
        yt = YouTube(url)
        stream = yt.streams.get_highest_resolution()            
        stream.download(output_path=DOWNLOAD_FOLDER)
        
    print(p.title + " 다운로드 완료\n")

if __name__ == "__main__":
    
    # 다운로드 받을 플레이리스트 url을 리스트에 넣어줌
    playlist_url =  ['https://www.youtube.com/watch?v=~~~~~~', 
                 'https://youtube.com/playlist?list=~~~~~~~~~~~',
                 'https://youtube.com/playlist?list=~~~~~~~',
                 'https://youtube.com/playlist?list=~~~~~~~~~',
                 'https://youtube.com/playlist?list=~~~~~~~~-',
                 'https://youtube.com/playlist?list=~~~~~~-5mWbx0zdG0betdeoL']
    
    # 플레이리스트 url을 담고 있는 리스트를 반복문 안 에서 다운로드 함수 매개변수에 할당해주면서 실행
    for i in playlist_url:
        playlist_download(i)

추가로 단일 유튜브 영상을 받고 싶으시면 아래 처럼 간단하게 구현할 수 있습니다.

from pytube import YouTube
url = '유튜브 동영상 url (플레이리스트 url 아님!)'
DOWNLOAD_FOLDER = '다운로드 받을 폴더 경로' #빈값('')으로 두면 파이썬 소스파일이 있는 폴더에 다운로드 받습니다
yt = YouTube(url)
stream = yt.streams.get_highest_resolution()            
stream.download(output_path=DOWNLOAD_FOLDER)

+ Recent posts