반응형

안녕하세요. 정말 오랜만의 포스팅입니다.

그동안 현생에 치여서 포스트를 많이 못한 것을 반성하고 있습니다.

기술은 빠르게 변화하고 있습니다. 그 중 제가 요즘 관심을 가지고 있는것은 바이브 코딩입니다.

 

바이브 코딩(Vibe Coding)이란?

영어로(Vibe)는 '느낌, 분위기'를 의미합니다. 

한때 한국에서도 이런 말이 있었죠. "짬에서 나오는 바이브" 즉 '경험에서 나오는 분위기' 이렇게 이해할 수 있는데요,

간단히 말하면 내가 원하는 분위기(느낌)으로 코딩을 하는 것을 '바이브코딩' 이라고 보시면 되겠습니다.

더 나아가서, 개발자가 코드의 모든 세부 구현에 작성하기보다, 만들고 싶은 결과,의도,느낌(vibe)을 먼저 설명하고 AI의 도움을 받아 코드를 완성해 나가는 개발 방식을 의미합니다.

전통적인 코딩 vs 바이브 코딩

전통적인 코딩이 해당 개발 언어를 알아야 하고(문법 이해), 먼저 어떻게 만들것인지 다 정해놓고(로직 설계), 개발하며 오류를 해결(디버깅) 하는 순서로 간다고 한다면,

바이브 코딩은 내가 '어떤것을 만들고 싶다' , '이런 기능이 있었으면 좋겠다' 만 있으면 그것을 자연어로만 작성해도 AI가 알아서 개발을 해준다는 차이점이 있습니다.

 

바이브 코딩의 장점
  1. 초보자도 개발을 할 수 있다.
    : 자연어(사람이 사용하는 언어)로 내가 원하는 기능, 결과물에 대한 의도를 설명할 수 있기 때문에 해당 프로그래밍 언어를 몰라도 AI를 활용하여 개발이 가능합니다.

  2.  개발 속도가 빠르다.
    : 반복적인 코드나 기본 구조를 AI가 대신 만들어 주어서 PoC(Proof of Concept)와 같은 프로토타입 제작을 빨리 할 수 있습니다.

  3. 아이디어 중심의 사고가 가능하다.
    : "어떤 알고리즘을 쓰고 어떻게 구현할까?" 보다 "무엇을 만들고 싶은가?"에 집중할 수 있어 기획자, 디자이너, 비전공자에게도 유리합니다.

  4. 코딩 학습에도 도움이 된다.
    :  또한 이미 코드를 알고 있는 사람들에게는 AI가 생성한 코드를 확인하며 자주 나오는 코드 구조와 패턴을 자연스럽게 학습할 수 있습니다.

 

그럼 이번에는 바이브 코딩을 할 수 있도록 도와주는 도구들에 대해 간단히 소개를 해 보도록 하겠습니다.

바이브 코딩을 위한 여러 툴들이 있지만 그중에서 제가 현재까지 사용해본 플랫폼 3가지 정도를 간단하게 소개해보고자 합니다.

바이브 코딩이 가능한 플랫폼들: Lovable, Cursor, Google Antigravity 
  • Lovable(러버블)
    :Lovable은 자연어로 설명한 아이디어를 바탕으로 웹 서비스나 앱의 기본 형태를 만들어 주는 AI플랫폼입니다.
    Lovable을 활용하면 기획 부터 구현 배포까지 한번에 구현할 수 있다는 장점이 있습니다.
    또한 다른 툴들에 비해서 웹 브라우저에서 바로 개발하며, 초보자가 사용하기 쉽다는 장점이 있습니다. 
    처음 로그인하면 매달 무료 크레딧을 주고 이후 모두 소진 시 유료로 크레딧 플랜을 구매해 사용해야 합니다.
    https://lovable.dev/
 

Lovable - Build Apps & Websites with AI, Fast | No Code App Builder

Build apps, websites, and digital products faster using Lovable’s no-code and AI-powered platform, no deep coding skills required.

lovable.dev

  • Cursor(커서)
    : Cursor는 AI가 깊게 통합된 코드 에디터로, VS Code와 유사한 환경을 제공합니다.
    코드 작성 중 AI가 실시간으로 보조하고, 자연어로 코드 수정을 요청할 수 있으며, 기존의 코드 분석과 리팩토링에 강점이 있습니다.
    개인적으로 커서는 특히 개발자에게 더 특화된 플랫폼이라고 생각합니다. 
    커서 역시 무료 크레딧을 제공하며, 러버블과 마찬가지로 크레딧 소진시 유료 결제를 해야 더 사용할 수 있습니다.
    https://cursor.com/
 

Cursor

Built to make you extraordinarily productive, Cursor is the best way to build software with AI.

cursor.com

  • Google Antigravity(구글 안티그래비티)
    : 구글에서 작년 2025년 11월에 공개한 IDE 입니다. 에이전트 중심(agent-first)으로, 사람이 코드를 하나하나 작성하기 보다 AI 에이전트에게 일을 맡기고 방향을 잡아주는 방식으로 사용할 수 있습니다. AI는 브라우저 같은 여러 환경에서 알아서 작업을 진행하고, 사용자와 대화하벼 원하는 방향으로 결과물을 만들 수 있습니다.
    개인적으로 사용해 보았을때는 Cursor와 UI가 비슷하며(둘 다 VS Code 기반이라) 속도는 커서보다 조금 느리다고 느꼈습니다.
    현재 무료로 사용할 수 있으며, 사용량이 많으면 잠시 기다려야 다시 쓸수 있다고 합니다. 
    https://antigravity.google/
 

Google Antigravity

Google Antigravity - Build the new way

antigravity.google

 

Lovable, Cursor, Google Antigravity 비교 표
항목 Lovable Cursor Google Antigravity
사용 방식 웹 기반 서비스
: 브라우저에서 시작, 별도 설치 없음. (자연어 입력으로 앱 생성)
앱/플러그인 형태
: VS Code 기반 IDE에서 사용(설치/설정 필요)
다운로드형 IDE
: Windows, macOS, Linux용 설치 프로그램 제공
코드 중심성 낮음
: 자연어로 전체 앱/서비스 생성, 코드 출력은 자동 생성 중심
높음
: 코드 편집·생성·리팩토링 중심, 기존 코드의 이해와 수정 지원
높음
: AI 에이전트가 코드 작성·검증·실행까지 주도, 전통 IDE와 유사한 인터페이스 제공
유/무료 여부 유료+무료
: 일반적으로 일부 무료 플랜/체험 가능, 유료 구독 옵션 존재 (기능/사용량 확장)
유료+무료
: 무료 플랜과 Pro/Teams 요금제 존재
무료(프리뷰)
: 현재 공개 프리뷰로 무료 사용 가능, 유료 구독 연동 옵션도 존재
초보자 적합도 ★★★★ ★★★ ★★
설명 자연어만으로 앱을 만들 수 있어 코딩 경험이 없어도 빠르게 결과물을 확인 가능 개발자 도구에 익숙하면 빠르게 AI 와 함께 코딩 생산성을 높일 수 있음 IDE 설치/설정이 필요하고, AI 에이전트도 개발 맥락을 어느 정도 이해해야 함

 

마무리

바이브 코딩을 하다 보면 요즘 같은 AI시대의 코딩은 점점 프로그래밍언어를 알고 문법에 맞춰 구현한다기 보다,

내가 만들고 싶은 것에 대한 기획을 잘 하고 그것을 잘 설명하여 AI가 결과물을 만들어 내게 하느냐로 바뀌고 있는 것 같습니다.

저는 오늘 제가 사용한 경험이 있는 3개의 플랫폼들만 소개를 했지만, Claude Code 같이 요즘 뜨고 있는 바이브 코딩 툴도 있습니다. 

저도 조만간 사용해볼 계획입니다. 

여러분 중에서도 더 알고 있는 툴들이 있다면 댓글로 남겨주시면 좋을 것 같습니다. 

반응형
반응형

가끔 드래그하여 복사 붙여넣기를 하려고 할 때 안되는 웹사이트들이 있습니다.

이런 상황에서 사용할 수 있는 유용한 방법을 알려드리도록 하겠습니다.

 

드래그가 막혀있는 사이트에서 드래그 할 수 있는 방법
1. 복사 붙여넣기 하려는 웹사이트 접속

 

2. F12키 누르기

 

3. 우측 상단의 톱니바퀴 모양(설정) 누르기

 

4. Settings의 Preferences 탭에서 아래로 쭉 내려 Debugger로 이동하기

 

5. Disable JavaScript에 체크하기
6. 드래그 하고 싶은 부분 드래그 하기

 

7. 복사 붙여넣기가 끝나면 Disable JavaScript 다시 해제해 주기

이렇게 하면 드래그가 가능합니다.

다 끝나면 다시 해제해 주는거 잊지 마세요!

자바스크립트 사용을 해제해 놓는 거라서

다시 해제하지 않으면 사이트 내 클릭 등 주요 기능이 안될 수 있습니다.

이제 어디서든 코드를 Ctrl+c Ctrl+v 할 수 있습니다.

반응형

'기타' 카테고리의 다른 글

Tistory 블로그에 html 파일을 iframe으로 삽입하기  (2) 2022.03.15
반응형

안녕하세요.

크롤러를 만들다 보면,

내가 가져오고 싶은 부분이 어디에 위치해 있는지 알아야 할 때가 있습니다.

그 때 개발자도구를 사용하면 해당 사이트 html의 어느 부분에 있는지 금방 파악이 가능합니다.

지금부터 그 방법을 같이 알아보도록 하겠습니다.

 

여기에서 사용할 예시 사이트는 네이버 뉴스의 어느 한 기사 입니다.

- 예시 사이트: https://n.news.naver.com/article/666/0000019702

위의 사이트를 클릭해서 들어가 주세요.

위와 같은 기사가 보일 것입니다.

1. F12키를 눌러 개발자 도구 열기

우리가 만약 기사 제목을 수집하고 싶다고 가정해 봅시다.

제목을 가져오려면 html에 어디에 제목이 위치해 있는지 알아야 할 것입니다.

이 때 개발자 도구를 열어줍니다.

개발자 도구는 F12키를 누르면 확인할 수 있습니다.

위와 같이 우측에 창이 생길 것입니다.

하지만 소스 코드 전체를 한눈에 보기엔 어려움이 있습니다.

제목 또한 어디에 있는지 알기 어렵습니다. 

이럴 때는 요소를 클릭하면 바로 알 수 있습니다.

 

2. 요소 선택하기

위의 개발자 도구 창을 보면 좌측 상단에 커서 아이콘이 보입니다.

이 아이콘은 페이지에서 요소를 선택해 검사할 수 있는 기능을 가지고 있습니다.

위의 사진에서 빨간색 박스로 표시된 아이콘을 클릭 후 왼쪽에 기사에 내가 확인하고 싶은 기사에 커서를 가져가면

아래 사진과 같이 파란색으로 표시가 됩니다.

그후 오른쪽 창을 보면 아까는 보이지 않았던 제목 부분이 보입니다.

여기서 원래대로라면 body 밑에 div class name이 end_container인것 밑에 div ct_wrap 밑에 ct_scroll_wrapper 밑에 newsct... 밑에 이런 식으로 쭉쭉 타고 내려가서 h2에 span 에 제목이 위치해 있는 것을 확인할 수 있겠습니다만 귀찮고 복잡합니다.

이렇게 하나하나 눈으로 봐도 되지만 이 대신에  copy selector를 사용하면

더 간단하게 Beautiful Soup의 html selector를 사용해서 바로 가져올 수 있습니다.

3. selector 복사하기

copy selector는 간단합니다.

아까 찾은 개발자 도구에서 제목부분 우클릭을 하고 Copy(복사) 클릭, Copy selector 클릭하면 복사가 됩니다.

이렇게 하고 Ctrl+V를 해서 붙여넣기를 하면 아래와 같이 복사됩니다.

#title_area > span

위의 뜻은 id가 title_area 아래의 span 태그에 제목이 위치해 있다는 것을 뜻합니다.

이것을 만약 Beautiful Soup의 select로 가져오려면 아래처럼 작성하면 제목을 가져오는 것을 확인할 수 있습니다.

#크롤링시 필요한 라이브러리 불러오기
from bs4 import BeautifulSoup
import requests

#테스트 기사
test_url = "https://n.news.naver.com/article/666/0000019702"

# ConnectionError방지
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4758.102"}

news = requests.get(test_url,headers=headers)
news_html = BeautifulSoup(news.text,"html.parser")

title = news_html.select("#title_area > span")
title
 

결과: [<span>폭염으로 닭 폐사에 크기까지 줄어든 계란…“왕란이 사라졌다”</span>]

 

이런 식으로 다른 부분들도 개발자 도구를 이용하면 간단하게 가져올 수 있습니다.

반응형
반응형
IPv6

IPv4의 기존 32bit 주소 공간이 인터넷 사용자 증가에 따라 고갈되어 128bit 주소 공간을 제공하는 IPv6가 등장하게 되었다.

IPv6는 네트워크의 물리적 위치에 제한받지 않고 같은 주소를 유지한다.

 

패키지 다이어그램(Package Diagram)

시스템의 서로 다른 패키지들 사이의 의존관계를 표현하기 위한 다이어그램. 패키지와 의존관계로 표현한다.

- 참고자료

https://www.uml-diagrams.org/package-diagrams-overview.html

 

UML package diagrams overview - common types of package diagrams - package diagrams and model diagrams.

UML Package Diagrams Overview Package diagram is UML structure diagram which shows structure of the designed system at the level of packages. The following elements are typically drawn in a package diagram: package, packageable element, dependency, element

www.uml-diagrams.org

 

DB 회복기법

- 로그 기반 회복 기법

  • 지연 갱신 회복 기법: 트랜잭션이 완료되기 전까지 데이터베이스에 기록하지 않는 기법
  • 즉각 갱신 회복 기법: 트랜잭션 수행 중 갱신 결과를 바로 데이터베이스에 반영하는 기법

- 체크포인트 회복 기법: 장애 발생 시 검사점 이후에 처리된 트랜잭션에 대해서만 장애 발생 이전의 상태로 복원시키는 회복 기법

- 그림자 페이징 회복 기법: DB 트랜잭션 수행 시 복제본을 생성하여 데이터베이스 장애 시 이를 이용해 복구하는 기법

 

네트워크 공격 기법

 

이름 설명
스니핑(Sniffing) 공격 대상에게 직접 공격을 하지 않고 데이터만 몰래 들여다보는 공격 기법(수동적)
네트워크 스캐너, 스니퍼 네트워크 HW,SW 구성의 취약점 파악을 위해 공격자가 취약점을 탐색하는 공격 기법
패스워드 크래킹(Password Cracking) 아래와 같은 공격을 활용함
- 사전(Dictionary) 크래킹: ID와 PW가 될 가능성이 있는 단어를 파일로 만들어 놓고 이 파일의 단어를 대입하여 크랙하는 공격 기법
- 무차별 크래킹: PW로 사용될 수 있는 영문자, 숫자, 특수문자 등을 무작위로 대입하여 비번을 알아내는 공격 기법
- 패스워드 하이브리드 공격: 사전 , 무차별 대입 공격을 결합하여 공격하는 기법
- 레인보우 테이블 공격: 비번별로 해시값을 미리 생성하여 테이블에 모아 두고, 크래킹하고자 하는 해시값을 테이블에서 검색해서 역으로 비번을 찾는 공격 기법
IP 스푸핑(IP Spoofing) 침입자가 인증된 컴퓨팅 시스템인 것처럼 속여서 타깃의 시스템 정보를 빼내기 위해 본인의 패킷 헤더를 인증된 호스트의 IP 주소로 위조해 타깃에 전송하는 공격 기법
ARP 스푸핑 공격자가 특정 호스트의 MAC 주소를 자신의 MAC 주소로 위조한 APR Reply를 만들어 희생자에게 지속적으로 전송하여 희생자의 APR 캐시 테이블에 특정 호스트의 MAC 정보를 공격자의 MAC 정보로 변경, 희생자로부터 특정 호스트로 나가는 패킷을 공격자가 스니핑하는 공격 기법
ICMP Redirect 공격 - 3계층에서 스니핑 시스템을 네트워크에 존재- 하는 또다른 라우터라고 알림으로써 패킷의 흐름을 바꾸는 공격 기법
- 메시지를 공격자가 원하는 형태로 만들어 특정 목적지로 가는 패킷을 공격자가 스니핑하는 공격 기법
트로이 목마 악성 루틴이 숨어 있는 프로그램으로 겉보기에 정상적인 프로그램으로 보이지만 실행하면 악성 코드를 실행하는 프로그램

 

SW 개발 보안의 3요소

 

요소 설명
기밀성(Confidentiality) 인가되지 않은 개인 or 시스템 접근에 따른 정보 공개 및 노출을 차단하는 특성
무결성(Integrity) 정당한 방법을 따르지 않고서 데이터가 변경될 수 없으며, 데이터의 정확성 및 완전성과 고의 또는 악의로 변경되거나 훼손 또는 파괴되지 않음을 보장하는 특성
가용성(Availability) 권한을 가진 사용자나 애플리케이션이 원하는 서비스를 지속해서 사용할 수 있도록 보장하는 특성

 

반응형
반응형

 

디지털 포렌식(Digital Forensics)

: 범죄 행위에 대한 사실을 사법기관에 제출하기 위해 디지털 증거자료를 획득, 분석, 보관, 제출 기록하는 일련의 절차 및 방법을 말함.

디지털 포렌식의 원칙은 정당성, 재현성, 연계성, 신속성, 무결성이 있다.

 

루트킷(Rootkit)

: 해커가 시스템의 민감한 정보를 수집 또는 네트워크상의 다른 시스템을 공격 또는 추적 회피를 위한 중간 지점으로 이용하더라도 로그를 지워버릴 수 있어 탐지하기 어려운 도구를 말한다. 주로 불법적인 해킹에 사용되는 기능을 제공하는 프로그램의 모음.

 

크라임웨어(Crimeware)

: 온라인상에서 범죄와 같은 불법적인 행위를 수행하기 위해 제작된 컴퓨터 프로그램.(공격용 툴킷)

- 악성 코드로 구성된 프로그램이 사용자를 속여 PC에 설치되면 그 안에 있는 정보 수집 또는 자원을 사용하여 다른 대상을 공격하는것에 이용되기도 한다. 
- 키로거, 스파이웨어, 브라우저 하이잭커 등이 크라임웨어에 속한다.

 

개발환경 인프라 구성 방식
방식 설명
온프레미스(On-Premise) 외부 인터넷망이 차단된 상태에서 인트라넷 망만을 활용하여 개발환경을 구축하는 방식
클라우드(Cloud) 아마존, 구글, 마이크로소프트 등 클라우드 공급 서비스를 하는 회사들의 서비스를 임대하여 개발환경을 구축하는 방식.
개발환경 투자비용이 적고 구축 시간이 빠르다.
하이브리드(Hybrid) 온프레미스와 클라우드 방식을 혼용하여 사용.

 

CASE 도구
case 유형 내용
상위 CASE
(Upper CASE)
계획수립, 요구분석, 기본설계 단계를 다이어그램으로 표현
모델들 사이의 모순 검사 및 모델의 오류 검증, 일관성 검증 지원
자료 흐름도 프로토타이핑 작성 지원 및 UI 설계 지원
하위 CASE
(Lower CASE)
구문 중심 편집 및 정적, 동적 테스트를 지원
시스템 명세서 생성 및 소스 코드 생성 지원

 

 

참고자료

수제비 2023 정보처리기사 실기 FINAL 실전 모의고사

반응형
반응형

안녕하세요.

그동안 python으로 여러 프로그램을 만들어 보았는데,

그걸 다른 사람에게도 보여주고 싶을 때는

1. python 설치

2. .py 파일 실행

이렇게 번거로운 과정이 필요할 것입니다.

하지만 그동안 만들었던 .py파일 프로그램을 .exe 파일로 만들 수 있다면

상대방 입장에서도 파일을 다운받아 실행하기만 하면 되니 엄청 간편할 것입니다.

이렇게 python 파일을 exe파일로 만들어주는 라이브러리가 있는데요,

그것은 바로 pyinstaller 라는 라이브러리 입니다.

 

pyinstaller 설치

설치 방법은 간단합니다. 터미널창에 아래와 같이 pip를 사용하여 간단히 설치할 수 있습니다.

pip install pyinstaller

 

pyinstaller 사용 방법

pyinstaller는 터미널에 여러 옵션을 주어 exe파일을 만들 수 있습니다.

그중 유용하게 쓰이는 옵션 몇가지를 알려드리자면,

--noconsole : exe파일 실행 시 콘솔창을 나타나지 않게 하기
--onefile : exe파일을 하나의 파일로 한번에 만들기
--icon: exe파일에 사용할 아이콘을 추가
--add-data: 데이터파일 추가

등등이 있습니다.

--icon 옵션을 사용할 때는 .ico, .png 파일 등등을 사용 가능합니다. 실행파일 아이콘이 되는 것이므로 배경은 투명한 배경의 아이콘이 좋습니다.

위의 몇가지 옵션들을 사용하여 exe 파일을 만든다면, 명령어는 아래와 같습니다.

pyinstaller --noconsole --onefile --icon=파일경로\아이콘.png/ico 파일경로\파이썬파일.py

예를 들어, minigame.py라는 파이썬 파일이 있고, star.png라는 아이콘 파일이 있으면 아래와 같이 작성하면 됩니다.

pyinstaller --noconsole --onefile --icon=star.png minigame.py

물론, 파이썬 파일과 png 파일은 해당 터미널 위치에 두 파일이 모두 있어야 합니다.

그러면 dist 파일 안에 exe파일이 만들어집니다.

 

이미지, 소리파일 등등을 .exe파일에 포함하는 방법

저는 전에 제가 pygame으로 만든 미니게임을 exe파일로 만들어 보도록 하겠습니다.

다만, 게임은 보통 이미지 파일과 효과음 등의 소리파일이 포함되어 있습니다.

저는 이 모든 파일을 하나의 exe파일에 포함을 하고 싶기 때문에 추가로 설정을 해주고 .exe파일을 만들어 보도록 하겠습니다.

1. 파이썬 파일(.py)에 설정값 넣어주기

exe파일로 만들려는. py파일 스크립트 맨 위에 아래와 같이 코드를 추가해줍니다.

import sys,os

if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
    os.chdir(sys._MEIPASS)

2. pyinstaller로 --add-data 파일/폴더 옵션 설정하여 exe파일 만들기 

만약 추가할 이미지 등의 파일이 한가지라면 --add-data 파일경로/파일 이렇게 끝에 옵션을 추가해 주면 됩니다.

저의 경우는 resource라는 폴더 안에 이미지, 소리 등의 파일이 다 들어있어서 폴더를 추가해 주도록 하겠습니다.

제 터미널 위치에 있는 파일 예시는 아래와 같습니다.

pygame/
|--- minigame.py
|--- resources/
     |--- enemy.jpg
     |--- player.jpg
     |--- game_over.wav
     |--- background.wav
     |--- babychick.ico

 

터미널이 위치한 pygame 폴더 안에

minigame.py라는 파이썬 게임파일과,

resources라는 게임을 동작하기 위해 필요한 이미지, 소리파일들이 있습니다.

저는 그리고 exe 아이콘으로 resources 폴더 안에 있는 babychick.ico라는 이미지를 사용하도록 하겠습니다.

(※참고: 아이콘 이미지는 여기에서 찾아서 다운받을 수 있습니다.)

이렇게 exe파일을 만들기 위한 명령어는 아래와 같습니다.

pyinstaller --noconsole --onefile --icon=resources\babychick.ico minigame.py --add-data "resources;resources"

--add -data 를 사용하여 resources폴더를 exe에 추가하였습니다.

그러면,

해당 pygame폴더 위치에 build, dist 등의 폴더가 생기며,(build 폴더는 삭제하셔도 exe 실행하는 데 문제가 없습니다.)

우리가 원하는 exe파일은 dist 폴더에 위치해 있습니다.

이 .exe파일만 따로 빼서 다른 사람들에게 보내면

추가로 파이썬을 설치하거나 할 필요 없이 바로 파일실행으로 게임이 실행됩니다:)

결과물

 

참고자료

https://pyinstaller.org/en/stable/index.html

 

PyInstaller Manual — PyInstaller 5.8.0 documentation

PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules. PyInstaller supports Python 3.7 and newer, and correctly bundles many major P

pyinstaller.org

https://api.arcade.academy/en/latest/tutorials/bundling_with_pyinstaller/index.html

 

Bundling a Game with PyInstaller - Python Arcade 2.6.17

Previous GPU Particle Burst

api.arcade.academy

 

마무리

제가 만든 .exe파일은 소리, 이미지 파일을 추가하다보니 용량이 커져서 실행 시작때 조금 느리지만(259MB 정도 됩니다...)

게임은 실행이 잘 되니 좋습니다:)

여러분들도 한번 그동안 만들었던 파이썬 파일로 실행파일 만들어서

친구,가족분들께 보여주면 좋을 것 같습니다.

반응형
반응형

안녕하세요.

이번에는 저번 pygame포스팅에 이어서 인트로와 아웃트로를 추가해 주도록 하겠습니다.

- 인트로: 게임 설명 및 시작, 종료 버튼 추가

- 아웃트로: 게임 스코어 안내 및 다시시작, 종료 버튼 추가

저번에는 따로 함수를 만들지 않았는데 이번에는

intro, game, outro 함수를 각각 만들어 연결해 보도록 하겠습니다.

이번 게시물의 결과물을 아래에서 미리 확인해 보세요:)

Preview

 

게임 기본 설정
import pygame, sys
from pygame.locals import *
import random, time

pygame.init()

# 초당 프레임 설정
FPS = 60
FramePerSec = pygame.time.Clock()

# 색상 세팅(RGB코드)
RED = (255, 0, 0)
ORANGE = (255, 153, 51)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
SEAGREEN = (60, 179, 113)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
VIOLET = (204, 153, 255)
PINK = (255, 153, 153)

GREY = (213,213,213)
LIGHT_GREY = (246,246,246)
LIGHT_BLACK = (76,76,76)
# 게임 진행에 필요한 변수들 설정
SPEED = 5  # 게임 진행 속도
SCORE = 0  # 플레이어 점수

# 폰트 설정
font = pygame.font.SysFont('Tahoma', 60)  # 기본 폰트 및 사이즈 설정(폰트1)
small_font = pygame.font.SysFont('Malgun Gothic', 20,bold=True)  # 작은 사이즈 폰트(폰트2)
middle_font = pygame.font.SysFont('Malgun Gothic', 40) # 중간 사이즈 폰트(폰트3)
game_over = font.render("GG", True, BLACK)  # 게임 종료시 문구

# 게임 배경화면
background = pygame.image.load('resources/background1.jpg')  # 배경화면 사진 로드

# 게임 화면 생성 및 설정
display_width = 640
display_height = 440
GameDisplay = pygame.display.set_mode((display_width,display_height))
GameDisplay.fill(PINK)
pygame.display.set_caption("Mini Game")

#점수 reset함수
def reset():
    global SCORE
    SCORE = 0
    return SCORE

 

Button 함수 만들기

Intro,outro에 사용할 버튼을 간단하게 만들기 위해 버튼을 만드는 함수를 하나 추가해 줍니다.

이 버튼 함수는 버튼 영역 안에 마우스 포인터가 들어가면 색이 바뀌고 클릭 시 True값을 return 합니다.

더 자세히 설명하자면 아래와 같습니다.

button(버튼안에 들어갈 메세지, x좌표,y좌표, 도형의가로길이,도형의세로길이,도형색, 포인터가 도형위에 위치시 변하는 색, action=True(클릭했을 때 이벤트 활성화), 버튼글씨색 설정 )

#버튼 생성 함수
def button(msg,x,y,w,h,ic,ac,action=None,fcolor=BLACK):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    #print(click)
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.ellipse(GameDisplay, ac,(x,y,w,h))

        if click[0] == 1 and action != None:
            return True
    else:
        pygame.draw.ellipse(GameDisplay, ic,(x,y,w,h))

    textSurf = middle_font.render(msg,True,fcolor)
    textRect = textSurf.get_rect()
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    GameDisplay.blit(textSurf, textRect)

 

Intro 만들기

게임 설명 텍스트를 위치시켜주고,

start, quit 버튼을 만들어서

start를 누를 시 게임을 시작하고, quit을 누르면 창이 닫히도록 game_intro 함수를 만들어 주었습니다.

# 시작(intro) 화면
def game_intro():
    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        # 배경화면 사진 게임창에 불러오기(사진, 위치)
        GameDisplay.blit(background, (0, 0)) #TODO
        # 텍스트 생성 및 배치하기
        large_Text = pygame.font.SysFont('Tahoma', 100)
        Text1,Text1Rect = text_objects("How to Play",large_Text)
        Text2,Text2Rect = text_objects("Use ← , → to avoid bombs!",middle_font)
        Text3,Text3Rect = text_objects("방향키 ← , →를 사용하여 폭탄을 피하세요!",small_font)
        Text1Rect.center = ((display_width/2),(display_height/4.5))
        Text2Rect.center = ((display_width/2),(display_height/2.5))
        Text3Rect.center = ((display_width/2),(display_height/2))
        GameDisplay.blit(Text1, Text1Rect)
        GameDisplay.blit(Text2,Text2Rect)
        GameDisplay.blit(Text3,Text3Rect)
        #start,quit버튼
        introBtn1 = button("START",display_width/6,display_height/1.7,200,100,BLACK,BLUE,action=True,fcolor=YELLOW)
        introBtn2 = button("QUIT",display_width/2,display_height/1.7,200,100,BLACK,RED,action=True,fcolor=YELLOW) 
        #버튼을 눌렀을 때
        if introBtn1 == True:
            return game()
        if introBtn2 ==True:
            pygame.quit()
            quit()
        pygame.display.update()
        FramePerSec.tick(FPS)

 

게임에서 동작할 class 만들기

게임에서 사용할 플레이어 및 적 개체 class를 저번 처럼만들어 줍니다.

## 게임 내에서 동작할 클래스 설정 ##

## 플레이어에게 적용할 클래스
class Player(pygame.sprite.Sprite):
    # 플레이어 이미지 로딩 및 설정 함수
    def __init__(self):
        super().__init__()
        # 플레이어 사진 불러오기
        self.image = pygame.image.load('resources/chick.png')
        # 이미지 크기의 직사각형 모양 불러오기
        self.rect = self.image.get_rect()
        # rec 크기 축소(충돌판정 이미지에 맞추기 위함)
        self.rect = self.rect.inflate(-20,-20)
        # 이미지 시작 위치 설정
        self.rect.center = (540, 390)

    # 플레이어 키보드움직임 설정 함수
    def move(self):
        prssdKeys = pygame.key.get_pressed()
        # 왼쪽 방향키를 누르면 5만큼 왼쪽 이동
        if self.rect.left > 0:
            if prssdKeys[K_LEFT]:
                self.rect.move_ip(-5, 0)
                position_p = self.rect.center
                return position_p
        # 오른쪽을 누르면 5만큼 오른쪽으로 이동
        if self.rect.right < 640:
            if prssdKeys[K_RIGHT]:
                self.rect.move_ip(5, 0)
                position_p = self.rect.center
                return position_p


## 적에게 적용할 클래스
class Enemy(pygame.sprite.Sprite):

    # 적의 이미지 로딩 및 설정 함수
    def __init__(self):
        super().__init__()
        # 적 사진 불러오기
        self.image = pygame.image.load('resources/boom2.png')
        # 이미지 크기의 직사각형 모양 불러오기
        self.rect = self.image.get_rect()
        # rec 크기 축소(충돌판정 이미지에 맞추기 위함)
        self.rect = self.rect.inflate(-20,-20)
        # 이미지 시작 위치 설정
        self.rect.center = (random.randint(40, 600), 0)

    # 적의 움직임 설정 함수+ 플레이어 점수 측정
    def move(self):
        global SCORE

        # 적을 10픽셀크기만큼 위에서 아래로 떨어지도록 설정
        self.rect.move_ip(0, SPEED)  # x,y좌표 설정
        # 이미지 가 화면 끝에 있으면(플레이어가 물체를 피하면) 다시 이미지 위치 세팅 + 1점 추가
        if (self.rect.bottom > 440):
            SCORE += 1
            self.rect.top = 0
            self.rect.center = (random.randint(30, 610), 0)
        return self.rect.center
게임 만들기

이제 위의 클래스를 사용하여 폭탄 피하기 게임을 만들어 줍니다.

게임 종료 시 outro화면으로 넘어갈 수 있도록 설정하는 것도 잊지 말고 넣어 줍니다.

###### 게임 설정 ########
# 플레이어 및 적 개체 생성
def game(speed = SPEED):

    P1 = Player()

    E1 = Enemy()

    # Sprites Groups 생성하기
    # 게임 물체들을 그룹화 하여 그룹별로 접근하여 설정 시 용이하게 만들기
    # 적(enemy) 객체 그룹화하기
    Enemies = pygame.sprite.Group()
    Enemies.add(E1)
    # 전체 그룹을 묶기
    All_groups = pygame.sprite.Group()
    All_groups.add(P1)
    All_groups.add(E1)

    # 적 개체 1초(1000ms)마다 새로 생기는 이벤트 생성
    increaseSpeed = pygame.USEREVENT + 1
    pygame.time.set_timer(increaseSpeed, 1000)

    # 게임 BGM 설정
    bgm = pygame.mixer.Sound('resources/backgroundMusic.mp3')
    bgm.play()
    ## 게임 루프 설정 ##
    # 게임 종료되기 전까지 실행되는 루프(이벤트) 설정
    while True:
        for event in pygame.event.get():
            # type increaseSpeed이면 속도 증가하여 어렵게 만듬(적 물체 이벤트)
            if event.type == increaseSpeed:
                speed += 0.5
            # 이벤트가 종료되면 게임도 종료시킴
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        # 배경화면 사진 게임창에 불러오기(사진, 위치)
        GameDisplay.blit(background, (0, 0))
        # 하단부에 위치할 스코어 점수(적을 피할때마다 +1점 증가)
        scores = small_font.render("Score: " + str(SCORE), True, BLACK)
        GameDisplay.blit(scores, (10, 400))

        # group1 = '<Player Sprite(in 1 groups)>'
        # group2 = '<Enemy Sprite(in 2 groups)>'

        # 게임 내 물체 움직임 생성
        for i in All_groups:
            GameDisplay.blit(i.image, i.rect)
            i.move()
            if str(i) == '<Player Sprite(in 1 groups)>':
                player_pos = i
            else:
                enemy_pos = i

        # <Player Sprite(in 1 groups)>
        # 플레이어 충돌 판정(게임종료)시
        if pygame.sprite.spritecollideany(P1, Enemies):
            for i in All_groups:
                i.kill()
            # 물체 이미지 변경(충돌후 변경되는 이미지)
            # 플레이어
            GameDisplay.blit(background, (0, 0))
            image0 = pygame.image.load('resources/chickbommed.png')
            image0.get_rect()
            GameDisplay.blit(image0, player_pos)

            # 폭탄
            image1 = pygame.image.load('resources/boomm.png')
            image1.get_rect()
            GameDisplay.blit(image1, enemy_pos)
            pygame.display.update()

            # 배경음악 멈춤
            bgm.stop()
            # 적과 충돌시 효과음 추가
            pygame.mixer.Sound('resources/BOOM.WAV').play()
            time.sleep(0.5)
            # 게임오버화면 설정
            pygame.mixer.Sound('resources/gameover.mp3').play()
            pygame.display.update()
            game_outro()

        pygame.display.update()
        # 초당 프레임 설정
        FramePerSec.tick(FPS)

 

Outro 만들기

게임 종료 화면을 만들어 줍니다.

게임 점수를 배치하고 버튼을 배치하여,

다시 플레이하고 싶은 사람은 score 리셋 후 retry를, 종료하고 싶은 사람은 quit을 눌러 창을 닫을 수 있도록 설정합니다.

## 게임오버 페이지
def game_outro():
    outro = True

    while outro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        GameDisplay.blit(background, (0, 0))
        final_scores = font.render("Your Score: " + str(SCORE), True, BLACK)
        Music = small_font.render("Music: www.bensound.com",True,BLACK)
        Photos = small_font.render("Photos: pixabay, pngwing",True,BLACK)
        Madeby = small_font.render("Made by wonhwa.tistory.com",True,BLACK)
        GameDisplay.blit(final_scores, (150, 100))
        GameDisplay.blit(game_over, (280, 200))
        GameDisplay.blit(Music,(10,400))
        GameDisplay.blit(Photos,(10,380))
        GameDisplay.blit(Madeby,(350,400))
        #retry,quit버튼
        outroBtn1 = button("RETRY",display_width/6,display_height/1.7,200,100,BLACK,BLUE,action=True,fcolor=YELLOW)
        outroBtn2 = button("QUIT",display_width/2,display_height/1.7,200,100,BLACK,RED,action=True,fcolor=YELLOW)
        #time.sleep(1)
        #pygame.display.update()
        #time.sleep(5) 
        #TODO: 버튼 누르면 동작
        if outroBtn1 == True:
            reset()
            game()
        if outroBtn2 ==True:
            pygame.quit()
            sys.exit()
        pygame.display.update()
        FramePerSec.tick(FPS)

 

게임 시작!

이제 만들어둔 함수를 호출하여 게임을 시작할 수 있습니다.

#####게임 시작#####
game_intro()

 

게임 파일

게임 파이썬 파일을 .exe파일로 만들어 보았습니다.(용량이 259MB로 꽤 큽니다..)

해보고 싶은 분들은 다운받아 실행해보시길 바랍니다 :)

https://drive.google.com/file/d/1fZGR-vbcTgAvsYqhsIh5lmnWSORJ0I0a/view?usp=sharing 

 

minigame.exe

 

drive.google.com

.py를 .exe로 만드는 방법은 아래의 링크를 참고해 주세요.

https://wonhwa.tistory.com/66

 

[python] pyinstaller로 이미지,소리파일이 포함된 .exe파일 만들기(feat.pygame)

안녕하세요. 그동안 python으로 여러 프로그램을 만들어 보았는데, 그걸 다른 사람에게도 보여주고 싶을 때는 1. python 설치 2. .py 파일 실행 이렇게 번거로운 과정이 필요할 것입니다. 하지만 그동

wonhwa.tistory.com

 

전체 코드

https://github.com/ElenaLim/Pygame/blob/main/minigame_ver1.1.py

 

GitHub - ElenaLim/Pygame: Minigame using Pygame

Minigame using Pygame. Contribute to ElenaLim/Pygame development by creating an account on GitHub.

github.com

참고자료

https://wonhwa.tistory.com/45

 

[python/Game] 파이썬으로 게임만들기(2) - 미니게임

이번 포스팅에서는 미니 게임을 pygame을 사용하여 만들어 보도록 하겠습니다. preview 이 게임은 병아리가 폭탄을 피하고 부딪히면 게임이 종료되는 미니게임 입니다. 게임 구성 1. 게임 화면 설정

wonhwa.tistory.com

https://pythonprogramming.net/pygame-button-function/

 

Python Programming Tutorials

PyGame Progress: 0% --> PyGame Buttons, part 4, creating a general PyGame button function Now that we've got some fancy code coming along, it's time to move all of this to a function, so that we can use this dynamically to create other buttons, rather than

pythonprogramming.net

 

마무리

그동안 저번에 만든 미니게임에 인트로,아웃트로를 넣고 싶었는데 드디어 완성할 수 있었네요.

exe파일도 올려두었으니 한번 씩 심심할 때 해보시면 좋을 것 같습니다 ㅎㅎ

반응형
반응형

안녕하세요.

저번 sklearn LDA 토픽 모델링 게시물에 이어서 이번에는 선정한 토픽에 대해

기간별로 어떻게 변화하는지를 확인해 보도록 하겠습니다.

 

데이터 준비

데이터는 저번 게시물에서 사용한 데이터를 사용하겠습니다.

- 데이터: 공공데이터 포탈의 '공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역' 

링크 들어가셔서

'공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역_20211227.csv' 

파일을 다운받아 주세요.

import pandas as pd
df = pd.read_csv('공정거래위원회_소비자 민원학습데이터 처리기관별 소비자 상담내역_20211227.csv',encoding='cp949')
print(df.head())
print(df.shape)

약 5만개의 행으로 이루어져 있습니다.

이 데이터에서 날짜 데이터도 있고 기타 데이터도 많지만,

토픽 모델링은 사건 제목을 가지고 해보도록 하겠습니다.

#토픽 토크나이저를 위해 필요한 부분 (사건제목) 추출
contents= df['사건제목(ACCIDENT_TITLE)']
contents

텍스트 토크나이징 및 카운트 벡터화

이제 이 텍스트를 가지고 sklearn을 사용하여 텍스트 토큰화 및 카운트 벡터화를 하겠습니다.

카운트 벡터는 sklearn.feature_extraction.text.CountVectorizer를 사용하여 생성할 수 있습니다.

저번 게시글과 마찬가지로, max_df=0.5로, min_df를 5로 지정하고 max_features 최대 2000개까지만 카운트벡터를 생성해 보겠습니다.

from konlpy.tag import Okt
from sklearn.feature_extraction.text import CountVectorizer
###형태소 분석###
okt = Okt()
def tokenizer(text):
    #명사 추출, 2글자 이상 단어 추출
    return [ word for word in okt.nouns(text) if len(word)>1]
Count_vector = CountVectorizer(tokenizer=tokenizer,
                              max_df = 0.5,
                              min_df = 5,
                              max_features = 2000)

%time minwon_cv = Count_vector.fit_transform(contents) 
print(minwon_cv[:5])
print(minwon_cv.shape)

이렇게 minwon_cv라는 민원 제목과 관련된 카운트벡터를 만들었습니다.

최적 토픽 수 선정하기

이번에는 토픽 수를 선정해 보겠습니다.

sklearn를 사용하는 경우, 혼란도만 제공하고 있는데, tmtoolkit을 사용하면 응집도도 구할 수 있습니다.

토픽에 따른 혼란도, 응집도 및 토픽 내용을 print해주는 함수를 하나 만들어 실행해 보도록 하겠습니다.토픽 수는 3에서 10까지 늘려 값을 확인해 보겠습니다.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import LatentDirichletAllocation
from tmtoolkit.topicmod.evaluate import metric_coherence_gensim

# 토픽별 단어를 보여주는 함수
def print_top_words(model, feature_names, n_top_words):
    for topic_idx, topic in enumerate(model.components_):
        print("토픽 #%d: " % topic_idx, end='')
        print(", ".join([feature_names[i]
                        for i in topic.argsort()[:-n_top_words -1:-1]]))
                        
# 혼란도 및 응집도 구하는 함수
def calc_pv_coherence(countVector,vocab, start=5, end=30, max_iter=10,topic_wp=0.1, doc_tp=1.0):
    num = []
    per_value = []
    cor_value = []
    for i in range(start,end+1):
        lda = LatentDirichletAllocation(n_components=i,max_iter=max_iter,
                                       topic_word_prior=topic_wp,
                                       doc_topic_prior=doc_tp,
                                       learning_method='batch', n_jobs=-1,
                                       random_state=0)
        lda.fit(countVector)
        num.append(i)
        pv = lda.perplexity(countVector)
        per_value.append(pv)
        coherence_score = metric_coherence_gensim(measure='u_mass',
                                                  top_n=10,
                                                  topic_word_distrib=lda.components_,
                                                 dtm=countVector,
                                                 vocab=vocab,
                                                 texts=None)
        cor_value.append(np.mean(coherence_score))
        
        print(f'토픽 수: {i}, 혼란도: {pv:0.4f}, 응집도:{np.mean(coherence_score):0.4f}')
        print_top_words(lda, vocab,10)
    
    plt.plot(num,per_value,'g-')
    plt.xlabel("topic_num")
    plt.ylabel("perplexity")
    plt.show()
    
    plt.plot(num,cor_value,'r--')
    plt.xlabel("topic_num")
    plt.ylabel("coherence_score")
    plt.show()
    return per_value,cor_value
per_values, cor_values = calc_pv_coherence(minwon_cv,names,start=3,end=10)

이렇게 토픽 갯수별 토픽 단어들이 나오고,

토픽별 혼란도, 응집도를 확인했을 때 최적의 토픽 수는 4 로 보입니다.

선정된 토픽 갯수로 LDA 토픽 모델링 하기

sklearn LDA를 사용해서 4개의 토픽을 가지고 있는 모델을 만들어 보겠습니다.

from sklearn.decomposition import LatentDirichletAllocation
lda = LatentDirichletAllocation(n_components=4,
                               n_jobs= -1,
                               random_state=0,
                               max_iter=10,
                                topic_word_prior=0.1,
                               doc_topic_prior=1.0,
                               learning_method='batch',
                               )
minwon_topics = lda.fit_transform(minwon_cv)

토픽 모델링 한 결과는 아래와 같습니다. 각 토픽별로 상위 20개 단어를 보도록 하겠습니다.

print_top_words(lda, Count_vector.get_feature_names_out(),20)

 

트렌드 확인하기

이제 이 민원 토픽들을 가지고 시간별로 어떤 종류의 토픽이 많이 나왔는지 확인하기 위한 트렌드 분석을 진행해 보겠습니다.

날짜 데이터는 '등록일자(RCPT_YMD)' 컬럼에 있습니다. 

행이 5만개가 되기 때문에 날짜를 월단위까지만 자른 데이터를 토픽 분포 데이터와 합치도록 하겠습니다.

from sklearn.feature_extraction.text import CountVectorizer
trend_data = pd.DataFrame(minwon_topics,columns=['토픽'+str(i) for i in range(1,5)])
trend_data = pd.concat([trend_data,df['등록일자(RCPT_YMD)'].map(lambda x:x[:7])], axis=1)
trend_data.head()

이후 groupby를 사용하여 월 단위로 토픽의 평균을 구해보겠습니다.

#월별 평균 구하기
trend = trend_data.groupby(['등록일자(RCPT_YMD)']).mean()
trend.head()

이제 월별로 토픽 비중이 어떻게 변했는지 확인하기 위해 matplotlib을 사용하여 그래프를 그려 보도록 하겠습니다.

matplotlib의 AutoDateLocator를 사용하여 x축은 6개월 단위로 눈금 및 값을 표시해서 보여주도록 하겠습니다.

import matplotlib
import matplotlib.pyplot as plt
from matplotlib import font_manager,rc
from matplotlib.dates import AutoDateLocator,MonthLocator
# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)
#날짜설정
locator = AutoDateLocator()
locator.intervald['MONTHLY'] = [6]

print_top_words(lda, Count_vector.get_feature_names_out(),20)

fig,axes = plt.subplots(2,2,figsize=(10,10))
for col,ax in zip(trend.columns.tolist(),axes.ravel()):
    ax.set_title(col)
    ax.xaxis.set_major_locator(locator)
    ax.axes.xaxis.set_visible(True)
    
    ax.plot(trend[col])

plt.show()

4개의 토픽에서 토픽별로 시간에 따라 분포가 어떻게 변화했는지 확인할 수 있습니다.

각 토픽 주제는 대략적으로

토픽 1: 피해 상담 문의

토픽2: 환불 및 반품 문의

토픽3: 수리 및 보상 문의

토픽4: 계약 해지 문의 

이렇게 볼 수 있을 것 같습니다.

토픽1 은 최근에 급격히 비중이 늘어났고, 토픽 3번은 시간에 따라 비중이 줄어들고 있고, 토픽 4번은 후반부에 비중이 늘어남을 확인할 수 있습니다.

 

 참고자료

1. 도서 - 파이썬 텍스트 마이닝 완벽 가이드(위키북스)

2.  https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.LatentDirichletAllocation.html

 

sklearn.decomposition.LatentDirichletAllocation

Examples using sklearn.decomposition.LatentDirichletAllocation: Topic extraction with Non-negative Matrix Factorization and Latent Dirichlet Allocation Topic extraction with Non-negative Matrix Fac...

scikit-learn.org

3. https://matplotlib.org/stable/api/dates_api.html

 

matplotlib.dates — Matplotlib 3.6.3 documentation

matplotlib.dates Matplotlib provides sophisticated date plotting capabilities, standing on the shoulders of python datetime and the add-on module dateutil. By default, Matplotlib uses the units machinery described in units to convert datetime.datetime, and

matplotlib.org

 

반응형

+ Recent posts