가장 인기있는 스크립트언어
<aside> 💡
파이썬
변수 선언의 일종
with urllib.request.urlopen(api_url) as response:
# 블록 안에서만 유효한 객체 response
# python도 함수 나가면 보통 정리되지만,
# 외부에서 참조하는 경우는 그렇지않은 등 변수 많음,
# 결국 가비지콜렉터를 못 믿어서 변수의 명시적 생애주기 설정해주는 박스 문법
# 변수 선언이라는 주요 기능만 본다면 아래와 같은 의미이다.
response = urllib.request.urlopen(api_url)
#########################################################################
################################ 전체예시 ################################
def get_latest_python_url_with_filename() -> Tuple[str, str]:
api_url = "<https://www.python.org/api/v2/downloads/release/>"
with urllib.request.urlopen(api_url) as response:
if response.status == 200:
list_releases = json.loads(response.read())
for dict_release in list_releases:
if dict_release["is_published"]:
for file in dict_release["files"]:
if "amd64.exe" in file["url"]:
file_name = file["url"].split("/")[-1]
return file["url"], file_name
else:
raise InstallSystem.ErrorPythonRelated(f"Failed to fetch data from API (HTTP {response.status})")
raise InstallSystem.ErrorPythonRelated("Failed to fetch the latest Python installer URL")
</aside>
<aside> 💡
Python
</aside>
| 표준모듈 (문서) | 설명 |
|---|---|
| os | 운영 체제 관련 기능을 제공합니다. |
| time | 시간 관련 기능을 제공합니다. |
| random | 난수 생성과 관련된 기능을 제공합니다. |
| functools | 고차 함수와 관련된 기능을 제공합니다. |
| itertools | 반복자 생성 함수를 제공합니다. |
| collections | 고성능 컨테이너 데이터 타입을 제공합니다. |
| unittest | 단위 테스트 프레임워크를 제공합니다. |
| logging | 로깅 기능을 제공합니다. |
| threading | 멀티스레딩 관련 기능을 제공합니다. |
| sqlite3 | SQLite 데이터베이스를 처리하는 기능을 제공합니다. |
| urllib | URL 관련 기능을 제공합니다. |
| http | HTTP 프로토콜 관련 기능을 제공합니다. |
| re | 정규 표현식을 처리하는 기능을 제공합니다. |
| json | JSON 데이터를 처리하는 기능을 제공합니다. |
| datetime | 날짜와 시간 관련 기능을 제공합니다. |
| math | 수학적 함수와 상수를 포함합니다. |
| sys | 파이썬 인터프리터와 관련된 기능을 제공합니다. |
| 패키지(라이브러리) | 설명 |
|---|---|
| NumPy | |
| pandas | |
| matplotlib | |
| SciPy | |
| ScikitLearn | |
"""
장문주석
입니다.
"""
class emptyClass(상속희망시부모클래스넣기):
pass # 아예 비어있으면 에러
class webServer():
def __init__(self): # 생성자
super().__init__() # 부모클래스의 생성자호출인데, 상속받은게 없다면 아무일도 일어나지않음 (관례적호출)
self._protectedVariable = 1 # protected접근지정자 표시
self.__privateVariable = 1 # private접근지정자 강제 (기본은 public)
self.debugMode = False # 맴버변수선언
self.setDefaultValue() # 단문주석입니다.
self.webApp = Flask(__name__)
self.webApp.config['TEMPLATES_AUTO_RELOAD'] = True
self.webControlConfig = configparser.ConfigParser()
self.apiServerConfig = configparser.ConfigParser()
self.setFlaskRoute()
self.createLogger()
self.flaskServerStart()
def __del__(self): # 명시적 소멸자
pass # 명시하는 순간, 암묵적 소멸기능 미작동으로 주의요망
def createLogger(self): # 맴버함수선언
logFormat = logging.Formatter('%(asctime)s - %(levelname)s > %(message)s')
self.webServer_logger = logging.getLogger("webServer") # 해당이름의 싱글톤생성, 로그출력시 해당이름출력
self.webServer_logger.setLevel(logging.DEBUG)
self.webServer_logger_Handler = logging.FileHandler("C:/glim/nffrollpressWebServer/log/webServer.log")
self.webServer_logger_Handler.setFormatter(logFormat)
self.webServer_logger.addHandler(self.webServer_logger_Handler)
def setFlaskRoute(self):
# 어노테이션-라우팅설정이기 때문에 실제실행되지는 않고 선언만 하는 느낌,
# 실제 함수의 중첩선언이라면 설령 같은 클래스라하더라도 외부에서 직접 호출은 불가하다
@self.webApp.route("/")
def index():
ret = self.webSelfTest()
if ret == True:
ret = render_template(self.indexPage,version = self.version)
return ret
...
if __name__ =='__main__': # 직접실행문법, 임포트되어 실행시 __main__은 해당 모듈이름가짐
webServer()
class apiServer():
def __init__(self):
super().__init__()
self.setDefaultValue()
self.webAppAPI = Flask(__name__) # 기본 Flask 객체 생성
self.apiServer = Api(self.webAppAPI) # Flask확장기능(url스타일 아키텍쳐) from flask_restful import Resource, Api, reqparse
CORS(self.webAppAPI, resources={r'*': {'origins': '*'}}) # 다중 도메인의 서버 동시이용 허용
apiClass.connectionDB() # 자체클래스
self.setFlaskRoute()
self.flaskServerStart()
self.apiServerDataLoad()
def apiServerDataLoad(self):
ret = False
if os.path.isfile(self.configFilePath + self.apiServerConfigFileName):
self.apiServerConfig.clear()
self.apiServerConfig = configparser.ConfigParser()
self.apiServerConfig.read(self.configFilePath + self.apiServerConfigFileName)
ret = True
return ret
def setFlaskRoute(self):
@self.webAppAPI.route("/")
def index():
if not apiClass._DB_Status:
# Database 연결 불가
ret = render_template(self.errorPage, # Flask 웹 프레임워크 템플릿렌더링
imageFileName = self.errorImageFileName,
title = self.errorTitle_DB_Connection_Error,
subTitle = self.errorSubTitle_DB_Connection_Error,
contents = self.errorContents_DB_Connection_Error,
redirectPage = self.refreshPage,
displayButtonName = self.refreshButtonDisplay)
else:
# 정상 페이지
ret = render_template(self.indexPage,
imageFileName = self.successImageFileName,
title = self.successTitle_apiServer_Index,
subTitle = self.successSubTitle_apiServer_Index,
contents = self.successContents_apiServer_Index,
redirectPage = "/")
return ret
@self.webAppAPI.errorhandler(404)
def errorHandler(error):
ret = render_template(self.errorPage,
imageFileName = self.errorImageFileName,
title = self.errorTitle_404,
subTitle = self.errorSubTitle_404,
contents = self.errorContents_404,
redirectPage = self.refreshPage,
displayButtonName = self.refreshButtonDisplay)
return ret
# Flask 서버에 API Resource 추가. 두번째인자url로 GET등의 요청이 오면 첫번째인자의 함수중에 해당하는 것을 실행, 매칭안되면 405error
self.apiServer.add_resource(apiClass.DB_Status, apiClass.DB_Status.accessAPI_Address)
self.apiServer.add_resource(...
self.apiServer.add_resource(...
...
...
-----------
# 아래 함수명과 HTTP매서드명의 매칭이 flask 프레임워크의 Resource클래스에 의해 강제되고있음
# 하단 Resource 클래스 구현부 참고
from flask import Flask
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
class ExampleResource(Resource):
def get(self):
# HTTP GET 메서드 처리
return {'message': 'GET request received'}
def post(self):
# HTTP POST 메서드 처리
return {'message': 'POST request received'}
def put(self):
# HTTP PUT 메서드 처리
return {'message': 'PUT request received'}
def delete(self):
# HTTP DELETE 메서드 처리
return {'message': 'DELETE request received'}
def patch(self):
# HTTP PATCH 메서드 처리
return {'message': 'PATCH request received'}
def options(self):
# HTTP OPTIONS 메서드 처리
return {'message': 'OPTIONS request received'}
def head(self):
# HTTP HEAD 메서드 처리
return '', 204 # HEAD 요청은 보통 응답 본문을 포함하지 않음
# 리소스와 URL 경로 연결
api.add_resource(ExampleResource, '/example')
if __name__ == '__main__':
app.run(debug=True)
-----------
"""
< 동작 원리 >
0. add_resource() 로 Resource클래스 내부의 map에 url과 목적클래스를 등록합니다.
1. 클라이언트가 서버에 HTTP 요청을 보냅니다. ( GET 등등등 )
2. Flask-RESTful은 Resource클래스 내부의 에서 요청된 URL과 매칭되는 를 찾습니다.
3. 매칭된 리소스 클래스의 dispatch_request() 메서드가 호출됩니다.
4. dispatch_request 메서드는 HTTP 메서드(GET, POST, PUT, DELETE 등)에 해당하는 리소스 클래스의 메서드를 찾아 호출합니다.
"""
class Resource(MethodView):
"""
Represents an abstract RESTful resource. Concrete resources should
extend from this class and expose methods for each supported HTTP
method. If a resource is invoked with an unsupported HTTP method,
the API will return a response with status 405 Method Not Allowed.
Otherwise the appropriate method is called and passed all arguments
from the url rule used when adding the resource to an Api instance. See
:meth:`~flask_restful.Api.add_resource` for details.
"""
representations = None
method_decorators = []
def dispatch_request(self, *args, **kwargs):
# Taken from flask
#noinspection PyUnresolvedReferences
# HTTP 요청 메서드 이름을 소문자로 변환한 후, 리소스 클래스에서 해당 이름의 메서드를 찾습니다.
meth = getattr(self, request.method.lower(), None)
# 만약 요청 메서드가 HEAD이고, head 메서드가 정의되어 있지 않다면, get 메서드를 대신 사용합니다.
if meth is None and request.method == 'HEAD':
meth = getattr(self, 'get', None)
# 해당 메서드가 존재하지 않는다면, 405 Method Not Allowed 상태 코드를 반환합니다.
assert meth is not None, 'Unimplemented method %r' % request.method
# Mapping : 아마도 class-url정보는 여기에 등록됨
if isinstance(self.method_decorators, Mapping):
decorators = self.method_decorators.get(request.method.lower(), [])
else:
decorators = self.method_decorators
for decorator in decorators:
meth = decorator(meth)
resp = meth(*args, **kwargs)
if isinstance(resp, ResponseBase): # There may be a better way to test
return resp
representations = self.representations or OrderedDict()
#noinspection PyUnresolvedReferences
mediatype = request.accept_mimetypes.best_match(representations, default=None)
if mediatype in representations:
data, code, headers = unpack(resp)
resp = representations[mediatype](data, code, headers)
resp.headers['Content-Type'] = mediatype
return resp
return resp
<body>
<div id="navbarContainer"><div data-include-path="{{ url_for('static', filename='html/sidebar_row.html') }}"></div></div>
<script>
window.addEventListener('load', function() { // 'load' 이벤트에 대해 다음함수 실행
var allElements = document.getElementsByTagName('*'); // 현재문서의 모든 태그네임 획득
Array.prototype.forEach.call(allElements, function(el) { // 현재문서의 모든 태그를 담은 객체에 대해(.call) 개별 태그를 인자로하여(el) 다음함수 수행
var includePath = el.dataset.includePath; // 개별태그의 data-include-path 확인
if (includePath) {
var xhttp = new XMLHttpRequest(); // AJAX 비동기통신지원 객체
xhttp.onreadystatechange = function () { // xhttp의 ready상태 바뀌면 다음함수 실행 (객체가 알아서)
if (this.readyState == 4 && this.status == 200) {
el.outerHTML = this.responseText; // 서버가 보내온 Text로 순회중인 태그의 outerHTML을 교체
document.querySelector('.index-page').classList.add('active');
document.querySelector('.form-switch').style.display = 'block';
releaseDate = '{{version}}';
setReleaseDate(releaseDate); } };
xhttp.open('GET', includePath, true); // url로 비동기(true) GET요청 세팅
xhttp.send(); // 서버로 전송 }
});
getDefectValue_Timer();
});
</script>
<div class="container">
<div class="headerSection mb-2">
<div class="currentLOT shadow p-1 me-2 bg-body rounded text-center placeholder-glow" id="currentLOT">
<div class="placeholder col-12 bg-secondary rounded"></div>
</div>
<div class="currentMeter shadow p-1 me-2 bg-body rounded text-center placeholder-glow" id="currentMeter">
<div class="placeholder col-12 bg-secondary rounded"></div>
</div>
<div class="currentDefectCount shadow p-1 me-2 bg-body rounded text-center placeholder-glow" id="currentDefectCount">
<div class="placeholder col-12 bg-secondary rounded"></div>
</div>
</div>
</div>
</body>