파이썬 유치원 (유아반)

1 파이썬 유치원

파이썬 유치원은 유튜브 채널 김왼손의 왼손코딩에서 구독자와 함께 진행하는 프로젝트입니다. 프로젝트 기간 동안 스스로 학습하면서 나만의 프로그램을 만들어 봅니다. 파이썬 유치원 1기는 2020년 5월 1일부터 31일까지 한달 동안 진행합니다.

파이썬 유치원에는 강의가 없습니다. 사실 강의만 들어서는 머리에 남는 게 없습니다. 직접 만들어 봐야 합니다. 모든 분야가 그렇겠지만 코딩은 더욱 그렇습니다. 이제 강의는 그만 듣고 직접 만들어 봅시다. 모든 정보는 유튜브와 구글에 있으니까요. 파이썬 유치원에서는 방향과 방법을 함께 고민합니다. 유치원 선생님은 아이가 하고 싶은 대로 자유롭게 두면서 아이가 흥미를 잃지 않게, 다치지 않게 옆에서 도와줍니다. 파이썬 유치원에서의 김왼손은 그런 역할입니다.

파이썬 유치원의 모든 진행 상황은 유튜브 채널 김왼손의 왼손코딩에서 공유합니다. 매주 토요일 저녁 유튜브 라이브에서 어떻게 하고 있는지 함께 살펴보고 어려움이 있다면 함께 고민합니다. 각자의 진행 내용은 제타위키의 파이썬 유치원 문서에서 공유합니다. 진행 내용을 공유하고 서로 의견을 나눌 수 있습니다.

파이썬 유치원 유아반은 파이썬이나 코딩을 배워본 적은 있지만 잘 하지 못하는 분들을 대상으로 합니다.

2 제타위키 사용법

3 유아반 친구들

3.1 김민재

3.1.1 설명

파이참을 이용해 계산기 기능과 디자인, 형태까지 만드는 코드

3.1.2 코드

from tkinter import *

window = Tk()
window.title("계산기")
equa = ""
equation = StringVar()


def press(value):
    global calc
    global value1
    if value != 'C':
        value1 = expression_field.get()
        value1 = value1 + value
        expression_field.delete(0, "end")
        expression_field.insert(0, value1)
    else:
        expression_field.delete(0, "end")
        calc = 0.0


def equalpress():
    calc = expression_field.get()
    total = str(eval(calc))

    expression_field.delete(0, END)

    expression_field.insert(0, total)

    calc = ""


calc = StringVar()

expression_field = Entry(window, width="50", bg="white")

expression_field.grid(row=0, column=0, columnspan=4)


expression_field.grid(row=0, column=0, columnspan=4)

button1 = Button(window, text=' 1 ',
                 command=lambda: press("1"), height=1, width=7)
button1.grid(row=3, column=0)

button2 = Button(window, text=' 2 ',
                 command=lambda: press("2"), height=1, width=7)
button2.grid(row=3, column=1)

button3 = Button(window, text=' 3 ',
                 command=lambda: press("3"), height=1, width=7)
button3.grid(row=3, column=2)

button4 = Button(window, text=' 4 ',
                 command=lambda: press("4"), height=1, width=7)
button4.grid(row=2, column=0)

button5 = Button(window, text=' 5 ',
                 command=lambda: press("5"), height=1, width=7)
button5.grid(row=2, column=1)

button6 = Button(window, text=' 6 ',
                 command=lambda: press("6"), height=1, width=7)
button6.grid(row=2, column=2)

button7 = Button(window, text=' 7 ',
                 command=lambda: press("7"), height=1, width=7)
button7.grid(row=1, column=0)

button8 = Button(window, text=' 8 ',
                 command=lambda: press("8"), height=1, width=7)
button8.grid(row=1, column=1)

button9 = Button(window, text=' 9 ',
                 command=lambda: press("9"), height=1, width=7)
button9.grid(row=1, column=2)

window.mainloop()
#일단은 숫자 셋팅 완료!!("여기까지 오느라 힘들었따;;;;")


3.2 김지수

3.2.1 설명

3.2.1.1 수준

한입에 쏙 파이썬 2/3 수강, 아직 익숙치 않아서 코드를 따라하면서 매우 낮은 수준의 엑셀 읽고 쓰기 가능

3.2.1.2 목표

업무자동화 프로그램

  • 엑셀파일 - pdf 파일(주로 table 자료)을 읽어서 엑셀에 작성
  • 함수와 macro를 이용하듯이 파이썬으로 엑셀을 활용하고 싶습니다. ( ex : 회사 재고의 수입된 날짜와 로트 별로 집계 금액 산출)
  • 항목별 책정된 금액을 재고 별로 할당하는 시스템. 예를 들자면 총 자금 100만원 중 50만원을 'A' 항목에 책정하고 그 금액은 'a1','a2','a3' 재고에만 할당시켜서 자동으로 매출매입현황을 파악할 수 있는 엑셀 환경을 파이썬으로 구축하고 싶습니다.
  • 관심있는 특정 키워드를 포함한 뉴스기사 서칭
  • '3'의 내용을 보고할 목적으로 이메일 전송

3.2.2 코드

from openpyxl import load_workbook
import pandas as pd
from pandas import Series, DataFrame
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
import os
import warnings 
warnings.filterwarnings("ignore")

def sort():
    ws1['A1'].value = '년'
    ws1['B1'].value = '월'
    ws1['C1'].value = '품목명'
    ws1['D1'].value = '수량'
    ws1['E1'].value = '단가'
    ws1['F1'].value = '공급가액'
    ws1['G1'].value = '부가세'
    ws1['H1'].value = '합계'
    ws1['I1'].value = '거래처명'
    ws1['J1'].value = '적요'

wb1 = load_workbook('testing.xlsx', data_only = True)
ws1 = wb1['Sheet1']
wb1.remove(wb1['Sheet1'])
ws1 = wb1.create_sheet('Sheet1')
ws1 = wb1['Sheet1']

sort()

user_input = '' 
user_input = input('몇 월 까지의 매출 자료를 불러옵니까? : ')
for month in range(1,int(user_input)+1):
    wb2 = load_workbook(str(str(month).zfill(2))+'매출.xlsx',data_only = True)
    ws2 = wb2['판매현황']
    for row1 in ws2.rows:
        if '계' and '일자' not in row1[0].value and '-' in row1[0].value :
            devision = [str(row1[0].value).split('/')[0], str(row1[0].value).split('/')[1],str(row1[1].value).split(' [')[0]]
            for num in range(2,9):
                devision.append(str(row1[num].value))
            ws1.append(devision)
 
#반복문으로 입력되게 수정
            
wb1.remove(wb1['Sheet2'])
ws1_2 = wb1.create_sheet('Sheet2')
user_input = '' 
user_input = input('몇 월, 몇 일의 재고 자료를 불러옵니까?(mmdd): ')

wb2 = load_workbook(user_input+'재고.xlsx',data_only = True)
ws2 = wb2['재고현황']
ws1_2 = wb1['Sheet2']

for row2 in ws2.rows:
    ws1_2.append([str(row2[1].value),str(row2[3].value)])

ws1_2.delete_rows(1)
ws1_2.delete_rows(int(ws1_2.max_row))
ws1_2.delete_rows(int(ws1_2.max_row))

wb1.save('testing.xlsx')

df = pd.read_excel('testing.xlsx', sheet_name = 'Sheet2')
df2 = pd.read_excel('testing.xlsx', sheet_name = 'Sheet1')
df2 = pd.merge(df2, df, how = 'left', on = '품목명')
df2.to_excel('testing_2.xlsx', index = False)

#vlookup 함수를 문자열로 사용하면 pivot_table로 활용할 때 값이 수식을 불러들여 NaN 값이 발생해서 pandas에서 merge를 활용해 vlookup을 구현, DataFrame을 엑셀로 저장

table_1 = pd.pivot_table(df2, index=['품목명','재고수량','거래처명'], columns=['년','월'], values=['수량'], aggfunc='sum')
table_2 = pd.pivot_table(df2, index=['품목명','재고수량'], columns=['년','월'], values=['수량'], aggfunc='sum')
writer = pd.ExcelWriter( 'ERP 매출 재고 통합자료.xlsx', engine = 'xlsxwriter')
table_2.to_excel(writer, sheet_name = 'Sheet1')
table_1.to_excel(writer, sheet_name = '거래처 포함')
writer.save()

#pandas의 pivot_table을 사용하여 엑셀의 피벗테이블을 구현

wb3 = excel.Workbooks.Open(str(os.path.dirname(os.path.realpath(__file__)))+'\\'+'ERP 매출 재고 통합자료.xlsx')

#다른 PC에서도 프로그램을 사용하므로 경로 입력을 현재 파일의 절대 경로를 문자열로 입력하고  파일 이름을 추가 해줌

ws3_1 = wb3.Worksheets("Sheet1")
ws3_2 = wb3.Worksheets("거래처 포함")
ws3_1.Columns.AutoFit()
ws3_2.Columns.AutoFit()
wb3.Save()
excel.Application.Quit()

#서식을 조작하여 열의 너비를 자동으로 맞추기 위해 추가한 코드


3.3 Kim KY

3.3.1 설명

장비가동률을 기반으로 한 장비별 전문화 아이템 산출

3.3.2 코드

# 파이썬 시작하기
a = input('program_number?')
i = input('연월일(yyyy.mm.dd)?')
year = i[0:4]
month = i[5:7]
date = i[8:]

print('='*50)
print('program_number #' + a)
print('Life is short, You need Python')
print(f'연도 : {year}년')
print(f'날짜 : {month}{date}일')
print('='*50)


3.4 김매매

3.4.1 수준

구글에 파이썬 예제라고 치면 나오는 300문제 다 풀 수 있음

3.4.2 목표

1.김매매: 휴대폰 배터리 상태와 온도 알림 어플 2. fps게임할때 화면을 확대해 스코프 없이도 줌을 할수 있는 프로그램(모바일 포함) 3. 버튼 하나로 음악을 재생, 정지를 해 게임 로딩시간을 지루하지 않게 하는 프로그램 4. 휴대폰 게임 할때 버튼 위치를 옮길 수 없을때 임의로 지정한 곳을 터치하면 버튼이 인식되는 어플 왠만하면 모바일로 갈거임

3.4.3 코드

#'국민 갓겜 가위바위보를 만들었습니다.'

print('게임을 시작합니다. 시작하려면 아무키나 입력하시고\n 종료하시려면 "종료"를 입력해 주세요')
skill=input()
list=['가위', '바위', '보']
win='제가 이겼군요 하핳'
lose='제가 졌군요ㅠㅠ'
tie='비겼네요 다시'
winc=0
losec=0
tiec=0
scissors=0
rock=0
paper=0
while skill!='종료':
    print('안 내면 진 거 가위바위보')
    skill=input()
    if skill=='가위':
        scissors+=1
        import random
        resurt=random.choice(list)
        print(resurt)
        if resurt=='가위':
            print(tie)
            tiec+=1
            print('\n')
        elif resurt=='바위':
            print(win)
            winc+=1
            print('\n')
        elif resurt=='보':
            print(lose)
            losec+=1
            print('\n')
    elif skill=='바위':
        rock+=1
        import random
        resurt=random.choice(list)
        print(resurt)
        if resurt=='가위':
            print(lose)
            losec+=1
            print('\n')
        elif resurt=='바위':
            print(tie)
            tiec+=1
            print('\n')
        elif resurt=='보':
            print(win)
            winc+=1
            print('\n')
    elif skill=='보':
        paper+=1
        import random
        resurt=random.choice(list)
        print(resurt)
        if resurt=='가위':
            print(win)
            winc+=1
            print('\n')
        elif resurt=='바위':
            print(lose)
            losec+=1
            print('\n')
        elif resurt=='보':
            print(tie)
            tiec+=1
            print('\n')
    else:
        if skill!='종료':
            print('이상한거 내지 말고 재대로 내봐요')
            print('\n')
    continue
print('게임이 종료돠었습니다.')
print('승리 :',winc)
print('패배 :',losec)
print('무승부 :',tiec)
print('\n')
print('가위를 낸 횟수 :',scissors)
print('바위를 낸 횟수 :',rock)
print('보를 낸 횟수 :',paper)
print('수고하셨습니다.')
input('창을 닫으시려면 아무 키나 입력하세요')


3.5 우유과자

3.5.1 설명

답변을 흡수해서 스스로 배우는 인공지능 챗봇을 만들고 싶습니다.

3.5.2 현황

디스코드 봇으로 현재

  • 주사위 기능
  • 핑을 알려주는 기능
  • 안녕이라고 하면 답변하는 기능
  • 메아리 처럼 말을 따라하는 기능
  • 명령어 목록을 보여주는 기능
  • 키워드와 답변을 저장하는 기능
  • 키워드로 저장된 답변을 불러오는 기능
  • 저장되어 있는 키워드와 답변을 수정하는 기능
  • 저장되어 있는 키워드와 답변을 삭제하는 기능
  • 시공조아

3.5.3 코드

import discord  # 디스코드 모듈을 가져옴
from discord.ext import commands  # 디스코드 명령어들을 가져옴
import random # 랜덤 함수를 가져옴
import asyncio
import openpyxl # 엑셀파일을 열고 수정하는데 쓰임

bot = commands.Bot(command_prefix='!')  # 봇 접두사 예: !안녕
token = '봇 토큰' # 봇 토큰

def learned(i, keyword): # 만약 시트에 같은 키워드가 적용되어 있다면 True를, 없다면 False를 리턴하는 함수
    file = openpyxl.load_workbook('memory.xlsx')
    sheet = file.active
    if sheet['A' + str(i)].value == keyword:
        return True
    else:
        return False

@bot.event
async def on_ready(): # 준비가 되면 출력
    print('We have logged in as {0.user}'.format(bot))
    print("ready")
    game = discord.Game("열일") # ~하는중으로 상태에 뜸
    await bot.change_presence(status=discord.Status.online, activity=game)

@bot.command()
async def 학습(ctx, *, content: str): # 키워드와 답변을 엑셀파일에 담는 커맨드
    file = openpyxl.load_workbook('memory.xlsx') # memory.xlsx라는 엑셀파일을 오픈 엑셀 파일 필요
    sheet = file.active # 엑셀파일 안에있는 값들을 불러와 저장
    learn = content.split(' ') # 키워드와 답변 분류
    if len(learn) > 1: # 형식 확인
        keyword = str(learn[0]) # 키워드는 맨 첫번째 단어
        answer = learn[1:] # 답변은 그 뒤에 모두
        for i in range(1, 101): # 엑셀에 남은 빈공간을 확인
            if learned(i, keyword): # 위에 있는 learned 함수에서 값을 받아 쓰는 구문
                await ctx.send("이미 존재하는 키워드 입니다!") # 값이 True 일때
                break
            else:
                if sheet['A' + str(i)].value == None: # 값이 False 일때 값이 들어 있지 않은 곳에 저장
                    sheet["A" + str(i)].value = keyword
                    sheet["B" + str(i)].value = " ".join(answer)
                    file.save('memory.xlsx') # 파일 세이브
                    await ctx.send("학습 완료 했습니다!") # 학습 완료 메세지
                    break
                elif i >= 100:
                    await ctx.send("저장할 수 있는 공간이 없어요!")
    else:
        await ctx.send("!학습 (키워드) (답)형식으로 해주세요!")

@bot.command()
async def 수정(ctx, *, content: str): # 값을 수정할 수 있는 함수 구조는 위에 !학습과 비슷
    file = openpyxl.load_workbook('memory.xlsx')
    sheet = file.active
    edit = content.split(' ')
    if len(edit) > 1:
        new_keyword = str(edit[0])
        new_answer = edit[1:]
        for i in range(1, 101):
            if learned(i, new_keyword):
                a = sheet['B' + str(i)].value
                sheet['B' + str(i)].value = None
                sheet['B' + str(i)].value = " ".join(new_answer)
                b = " ".join(new_answer)
                file.save('memory.xlsx')
                await ctx.send(f"{new_keyword} '{a}'(이)가 {new_keyword} '{b}'(으)로 수정되었어요!.")
                break
            elif i >= 100:
                await ctx.send("수정할 게 없네요. 그냥 저장하겠습니다.")
                await 학습(ctx, content=content) # !학습 함수를 불러와 저장
                break
    else:
        await ctx.send("!수정 (키워드) (답)형식으로 해주세요!")

@bot.command()
async def 지워(ctx, *, content: str):
    file = openpyxl.load_workbook('memory.xlsx')
    sheet = file.active
    delete = content.split(' ')
    if len(delete) < 2:
        del_keyword = str(delete[0])
        for i in range(1, 101):
            if learned(i, del_keyword):
                sheet['A' + str(i)].value = None
                sheet['B' + str(i)].value = None
                await ctx.send(f"{del_keyword}을(를) 성공적으로 지웠어요!")
                file.save('memory.xlsx')
                break
            elif i >= 100:
                await ctx.send(f"이 단어는 처음부터 없었는데요?")
                break
    else:
        await ctx.send("!지워 (키워드)형식으로 해주세요!")

@bot.command()
async def (ctx):
    latency = bot.latency #핑을 알려줌
    await ctx.send(f'퐁! {round(latency * 1000)}ms') #latency값을 ms단위에 맞게 1000을 곱한후 round를 이용해 소수점 첫째자리 반올림, f string을 이용해 출력

@bot.event
async def on_message(message):
    await bot.process_commands(message) # 이벤트와 명령을 함께 쓸 수 있게 도와줌 (중요!!)
    if message.author.bot:
        return

    if message.content.startswith('!안녕'):
        await message.channel.send('안녕하세요!')

    if message.content.startswith('!메아리'): # !메아리를 제외한 문장을 내보내 줌
        echo = message.content[4:]
        await message.channel.send(echo)

    if message.content.startswith('!주사위'): # 1~7까지 랜덤하게 출력.
        roll = random.randint(1, 7)
        if roll in [2, 4, 5]:
            await message.channel.send(f'{roll}가 나왔네요!')
        elif roll in [1, 3, 6]:
            await message.channel.send(f'{roll}이 나왔어요!')
        else:
            msg = await message.channel.send(f'{roll}이 나왔어요!(어라?)')
            await asyncio.sleep(1.0)
            await msg.edit(content='삐빗')

    if message.content.startswith("!명령어"): #명령어 목록을 임베드로 함
        embed = discord.Embed(title="Test Bot2의 명령어 목록", description="명령어들은 아래에 나와있습니다.", color=0x62c1cc)
        embed.set_footer(text=".")
        embed.add_field(name="!메아리 [문자열]", value="메아리가 울려 퍼지네요", inline=False)
        embed.add_field(name="!안녕", value="간단한 인사입니다.", inline=False)
        embed.add_field(name="!주사위", value="1~6중에 숫자가 나옵니다", inline=False)
        embed.add_field(name="!핑", value="당신의 핑을 알려드려요.", inline=False)
        embed.add_field(name="!학습", value="저장하고 싶은 값을 !학습 (키워드) (답)으로 적어주세요", inline=False)
        embed.add_field(name="기억", value="!학습으로 저장된 값을 -(키워드)로 불러올 수 있어요!", inline=False)
        embed.add_field(name="!수정", value="!학습으로 저장된 값을 !수정 (키워드) (답)으로 수정할 수 있어요!", inline=False)
        embed.add_field(name="!지워", value="!학습으로 저장된 값을 !지워 (키워드)로 지울 수 있어요!", inline=False)
        await message.channel.send(embed=embed)

    if message.content.startswith("시공조아"):
        url = 'https://youtu.be/0GxIGaRsWW0' # 시공조아 유튜브 url
        embed = discord.Embed(title="시공조아", description="시공의 폭풍은 정말 최고야!", color=0x62c1cc) # 가사
        embed.add_field(name=" . ", value="시이공 조아 시이공", inline=False)
        embed.add_field(name=" . ", value="조아 시이이 공조아", inline=False)
        embed.add_field(name=" . ", value="히오스", inline=False)
        fixing = discord.Embed(title='ERROR', description='ERROR FIXING...', color=0xFF0000)
        fixed = discord.Embed(title='ERROR FIXED', description='    ', color=0x62c1cc)
        msg = await message.channel.send(url)  # 고치기 위한 변수
        임베드 = await message.channel.send(embed=embed)
        await asyncio.sleep(31.0) # 영상 끝날 때까지 기다림
        await msg.delete() # 삭제
        await 임베드.edit(embed=fixing) # embed 수정
        await asyncio.sleep(2.5)
        await 임베드.edit(content='삐빗', embed=fixed)

    if message.content.startswith("-"): # -(키워드) 형식으로 사용
        file = openpyxl.load_workbook('memory.xlsx')
        sheet = file.active
        memory = message.content.split("-") # -를 제외해서 저장되지 않게 함
        m = memory[1]
        for i in range(1, 101):
            if sheet['A' + str(i)].value == m: # 만약 키워드와 저장되어 있는 값이 같다면
                await message.channel.send(sheet["B" + str(i)].value) # 답변을 출력
                break
            elif i >= 101: # 만약 반복문의 끝에 도달한다면(한마디로 저장되어 있는 값이 없다면)
                await message.channel.send("존재하지 않는 값이에요;;") # 존재하지 않는 값입니다를 출력
                break
bot.run(token)  # 실행


3.6 JT

3.6.1 설명

데이터 프로세싱과 Visualization 툴을 만들고 싶습니다.

3.6.1.1 목표1

데이터를 읽어와서 분석을 위한 데이터 프로세싱을 실행한다.

3.6.1.2 목표2

준비된 데이터를 다양한 그래프 형태로 도식화한다.

3.6.1.3 목표3

API를 통해 직접적으로 데이터를 불러들여온다.

3.6.2 코드

3.6.2.1 코드: 목표1
print('Hello Python!')
3.6.2.2 코드: 목표2
print('Hello Python!')
3.6.2.3 코드: 목표3
print('Hello Python!')


3.7 ckstmznf

3.7.1 설명

GUI를 이용해서 나를 소개하는 프로그램 만들기

3.7.2 참고영상

https://youtu.be/OtqWefBqbxA

3.7.3 1일차(부제 : 기획)

지난주 밖에 나가야 해서 참여를 못했지만---귀찮이즘이---PyQt5의 강의 영상은 꾸준히 보아 학습하였다. 오늘부터 시작을 한다. 먼저 기획을 한다면 기본 메뉴 ┌기본 프로필

             |─할수 있는 언어
             |─사용 할수 있는 소프트 웨어
            └기타 내용

3.7.4 코드

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

class Exam(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):
        x = 15

        btn_gibon = QPushButton("기본 메뉴 입니다.", self)
        btn_gibon.resize(btn_gibon.sizeHint())
        # btn_gibon.setToolTip("저의 기본 정보를 볼수 있는 메뉴입니다.")
        btn_gibon.move(50,x)
        x += 70

        btn_gibon = QPushButton("기본 정보", self)
        btn_gibon.resize(btn_gibon.sizeHint())
        btn_gibon.setToolTip("저의 기본 정보를 볼수 있는 메뉴입니다.")
        btn_gibon.move(50,x)
        x += 70

        btn_gibon = QPushButton("할수 있는 언어", self)
        btn_gibon.resize(btn_gibon.sizeHint())
        btn_gibon.setToolTip("제가 할수 있는 언어들입니다.")
        btn_gibon.move(50,x)
        x += 70

        btn_gibon = QPushButton("사용 할수 있는 소프트 웨어", self)
        btn_gibon.resize(btn_gibon.sizeHint())
        btn_gibon.setToolTip("제가 사용할수 있는 소프트 웨어들 입니다.")
        btn_gibon.move(50,x)
        x += 70

        btn_gibon = QPushButton("그 밖의 내용", self)
        btn_gibon.resize(btn_gibon.sizeHint())
        btn_gibon.setToolTip("그 밖의 기타 내용 입니다.")
        btn_gibon.move(50,x)
        
        self.setGeometry(500,500,400,400)
        self.setWindowTitle("기본 메뉴")
        self.show()


app = QApplication(sys.argv)
w = Exam()
sys.exit(app.exec_())

3.7.5 발전 내용

3.7.5.1 1일차

1일차 기획을 한 기본 메뉴들을 만들었다. 내가 지금 하고있는게 정석인지 안니지는 모르겠지만...

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}