과제
디렉토리 관리 프로그램을 참고하여 자신의 시나리오를 만들고 파일 관련된 프로그램을 작성해보자.
사원증 제작을 위한 사원 리스트 정리 프로그램
시나리오
평소에 정리를 잘해서 과제를 하려니 정리를 할만한 파일들이 없어 구상해본 시나리오
사원들의 사원증을 만들기위해 파일을 받아서 정리를 해서 제작의뢰를 해야한다.
제출을위해 사원들의 증명사진과 정보들은 받은뒤 엑셀에 정리를하고
정리후 폴더에 널부러져 있는 파일들을 깔끔하게 정리를 해보자
사원증 제작을 위한 사원리스트 정리 프로그램
- 사원의 정보는를 받는 양식은 증명사진 제목은 팀명_직급_사번_이름.jpg 기준으로 한다.
- 파일은 모두 사원증 이라는 디렉토리 안에 보관한다.
- 우선 사원증 디렉토리 안에 양식대로 제출한 파일들을 모두 읽어들인다.
- 읽어들인 정보들은 엑셀파일에 증명사진 사원명 팀명 직급 사번 순으로 정리 한다.
- 엑셀파일에 정리한후 팀명별로 폴더를 만든다.
- 각팀명 폴더 안에 해당하는 사원들의 파일들을 이동시켜 정리한다.
프로그램
# 필요한 모듈들을 먼저 import
import os
import shutil
import pathlib
import openpyxl as opx
from openpyxl.drawing.image import Image
# 전역으로 사용할 path 와 리스트를 선언
target_path = './사원증'
filelist = []
info_list = []
사용할 모듈과 리스트를 먼저 선언해주었고.
이후 파일정리를 할 클래스를 만들었다.
class CleanFolder: # 클래스를 선언
def __init__(self,target_path):
# 생성자를 만들고 디렉토리 주소를 받은후 클래스 안에서 사용할 변수들을 선언해준다.
self.temp_list = None
self.current_dir = target_path
self.filelist = [f for f in os.listdir(self.current_dir) if f.endswith('.jpg')] # filelist 안에 디렉토리에서 가져온 jpg 파일들만 담아준다
try: # 사원리스트.xlsx 라는 엑셀 파일을 불러오기
self.wb = opx.load_workbook('./사원증/사원리스트.xlsx')
except: # 만들어진 엑셀파일이 없다면 엑셀파일을 새로 만든다
self.wb = opx.Workbook()
self.ws = self.wb.active # 엑셀파일 사용을위한 변수 선언
def infoList(self): # 파일들의 정보를 리스트로 만들기위한 메서드
for file in self.filelist: # 파일리스트에 담긴 정보들을 하나씩 반복문에 담는다
self.temp_list = file.rstrip('.jpg').split('_') # 파일명에 확장자를 때어내고 언더바(_)를 기준으로 나누어서 리스트에 담아준다
info_list.append(self.temp_list)
return info_list
def categoryList(self): # 파일 분류를 위한 카테고리를 만들 메서드
self.category = []
for file in self.filelist:
temp_list = file.split('_')
self.category.append(temp_list[0]) # 파일명에서 언더바 기준으로 자른뒤 첫번째 인덱스인 팀명을 가져와서 리스트에 담는다
self.category = set(self.category) # 타입을 세트로 변경해 중복을 없애준다
return list(self.category) # 리스트 타입으로 변경해서 리턴
먼저 생성자를 선언후 파일 정리를위한 카테고리를 먼저 만들었다.(카테고리는 팀명)
def createxcell(self): # 엑셀을 만들기위한 메서드
categoryList = self.categoryList()
ord_sheet_name = self.wb.sheetnames
for sheetname in categoryList: # 카테고리명을 하나씩 반복문에 담는다.
if sheetname not in ord_sheet_name: # 중복되는 시트명이 없다면
self.wb.create_sheet(sheetname) # 팀명별로 시트를 하나씩 만들어준다.
ws = self.wb[sheetname]
if ws.cell(row=1, column=1).value != '사진':
ws.append(['사진', '사원명', '팀명', '직급', '사번'])
ws.move_range("A2:E2", rows=-1)
# 엑셀파일의 1행1열에 값이 없을시 사진,사원명,팀명,직급,사번 이라는 헤더를 만들어준다.
try:
self.wb.remove(self.wb['Sheet']) # 엑셀파일을 처음만들면 생성되는 기본 시트를 삭제해준다
except:
pass # 없다면 패스
self.wb.save(os.path.join(target_path, '사원리스트.xlsx'))
엑셀파일을 만들고 팀별로 시트를 만들어주었다,
def getFilename(self): # 사원들의 정보를 엑셀에 저장하기 위한 메서드
li = []
category = self.categoryList() # 팀명
infolist = self.infoList() # 파일리스트
for info in infolist: # 반복을위한 len값을 알아내기 위해 파일리스트의 하나씩 가져와 파일리스트의 0번 인덱스인 팀명만 빼내서 리스트에 담아준다
li.append(info[0])
for info in infolist: # 사원을 하나씩 뽑아와 if문으로 검사
if info[0] in category: # 팀명 카테고리 안에 해당 사원의 팀명이 있다면 코드를 실행
cnt = li.count(info[0]) # 해당 팀의 팀원이 몇명인지 알아내 cnt에 저장
self.ws.column_dimensions['A'].width = 18 # 증명사진이 들어갈 셀의 크기를 조정 사진이 들어갈 열은 고정이기 때문에 밖에서 선언
self.ws = self.wb[info[0]] # 해당사원이 속한 팀의 시트를 불러와준다.
image_path = os.path.join(self.current_dir, info[0] + '_' + info[1] + '_' + info[2] + '_' + info[3] + '.jpg') # 엑셀에 업로드할 jpg의 정확한path를 찾아낸다
img = Image(image_path)
img.width = 117 # 이미지크기를 조정
img.height = 156
for i in range(2, (2+cnt)): # 해당 팀의 팀원수 만큼 반복
if not self.ws.cell(row=i, column=2).value: # i번째 row에 2번째 column에 값이 없다면 실행
# 이때 이미지는 값으로 인식이 안돼기때문에 이미지가 아닌 문자열로 비교 하기위해 2번째컬럼으로 비교
self.ws.row_dimensions[i].height = 117
# 이미지가 들어갈 각셀의 높이를 설정 행은 한칸씩 내려가면서 정보를 추가해야하기 때문에 반복문 안에서 선언
self.ws.add_image(img, 'A' + str(i)) # A열의 i번째 행에 이미지를 삽입
self.ws.cell(row=i, column=2).value = info[3] # 이후 헤더에 맞춰 정보를 순서대로 입력
self.ws.cell(row=i, column=3).value = info[0]
self.ws.cell(row=i, column=4).value = info[1]
self.ws.cell(row=i, column=5).value = info[2]
break # 값이 입력이 되었다면 반복문 탈출
else: # 조건이 맞지않으면 패스
pass
self.wb.save(os.path.join(target_path, '사원리스트.xlsx')) # 엑셀파일 저장
return print('사원리스트 정리 완료') # 정상작동을 알리기위해 리턴
엑셀파일에 사원의 정보에 해당하는 사진과 파일명을 불러와 엑셀파일에 팀별로 정리를 했다.
def makeDir(self): # 파일을 정리할 폴더를 만드는 메서드
target_path = self.current_dir # 폴더를 만들 주소를 설정
categorylist = self.categoryList() # 팀명별로 폴더를 만들기위해 팀명카테고리를 가져온다
try:
for category in categorylist: # 팀명을 하나씩 불러와 폴더를 만들어준다.
new_dir = pathlib.Path(os.path.join(target_path, category))
new_dir.mkdir(parents=True, exist_ok=True)
# 이미 폴더가 있어도 에러를 만들지 않고 넘어가기위해 exist_ok=True 설정 오류가 발생하지 않으면 null값을 반환
except: # 이미 디렉터리가 생성 되어서 디렉터리 생성에 실패했을경우 예외처리
print('이미 폴더가 생성되었습니다.')
pass
return print('폴더 생성 완료')
def moveFile(self): # 파일을 옮기기 위한 함수 생성
folders = []
categorydic = {}
categorylist = self.categoryList()
file_list = os.listdir(self.current_dir)
jpg_files = self.filelist # 옮겨질 파일들의 리스트를 변수에 선언
for item in file_list:
item_path = os.path.join(target_path, item) # 파일 또는 폴더의 절대 경로 생성
if os.path.isdir(item_path):# 파일이 아닌 폴더(dir)일 경우에만 폴더리스트에 append
folders.append(item)
for file in jpg_files:
try:
temp_list = file.split('_') # split으로 분류명 을 저장
assert temp_list[0] in categorylist
categorydic[file] = temp_list[0] # {'파일명':'분류명'} 형식으로 딕셔너리로 저장
except:
pass
for key, value in categorydic.items(): # 딕셔너리에 키와 값을 따로 하나씩 불러온다
shutil.move(self.current_dir + '/' + key, self.current_dir + '/' + value) # 해당 주소로 파일이동
return print('파일 이동 완료')
팀별로 폴더를 만든후 해당 팀원들의 파일을 옮겨주었다.
class CleanUp: # 프로그램 작동을 위한 클래스
def __init__(self, target_path):
self.target_path = target_path
self.cf = CleanFolder(self.target_path)
# 생성자가 만들어지면 CleanFolder 클래스에 targetpath를 담고 실행
choice = input('사원파일 정리를 시작 하시겠습니까?: Y/N')
try:
if choice.upper() == 'Y': # 수락을 하였으면 파일정리를 시작
self.cf.createxcell()
self.cf.getFilename()
self.cf.makeDir()
self.cf.moveFile()
elif choice.upper() == 'N':
print('작업을 취소합니다.')
else:
print('입력을 확인하세요.')
except Exception as e:
print('에러발생 :',e)# 에러가 발생했을경우 보수를 위해 에러코드를 받아준다.
run = CleanUp(target_path) # 파일정리 실행
전체 실행
파일 정리 전
파일 정리 후
엑셀에 정보정리
폴더별로 파일정리
이후 사원증 폴더에 따로 추가해본 파일들도 잘 정리가 되었다.
전체코드
# 필요한 모듈들을 먼저 import
import os
import shutil
import pathlib
import openpyxl as opx
from openpyxl.drawing.image import Image
# 전역으로 사용할 path 와 리스트를 선언
target_path = './사원증'
filelist = []
info_list = []
class CleanFolder: # 클래스를 선언
def __init__(self,target_path):
# 생성자를 만들고 디렉토리 주소를 받은후 클래스 안에서 사용할 변수들을 선언해준다.
self.temp_list = None
self.current_dir = target_path
self.filelist = [f for f in os.listdir(self.current_dir) if f.endswith('.jpg')] # filelist 안에 디렉토리에서 가져온 jpg 파일들만 담아준다
try: # 사원리스트.xlsx 라는 엑셀 파일을 불러오기
self.wb = opx.load_workbook('./사원증/사원리스트.xlsx')
except: # 만들어진 엑셀파일이 없다면 엑셀파일을 새로 만든다
self.wb = opx.Workbook()
self.ws = self.wb.active # 엑셀파일 사용을위한 변수 선언
def infoList(self): # 파일들의 정보를 리스트로 만들기위한 메서드
for file in self.filelist: # 파일리스트에 담긴 정보들을 하나씩 반복문에 담는다
self.temp_list = file.rstrip('.jpg').split('_') # 파일명에 확장자를 때어내고 언더바(_)를 기준으로 나누어서 리스트에 담아준다
info_list.append(self.temp_list)
return info_list
def categoryList(self): # 파일 분류를 위한 카테고리를 만들 메서드
self.category = []
for file in self.filelist:
temp_list = file.split('_')
self.category.append(temp_list[0]) # 파일명에서 언더바 기준으로 자른뒤 첫번째 인덱스인 팀명을 가져와서 리스트에 담는다
self.category = set(self.category) # 타입을 세트로 변경해 중복을 없애준다
return list(self.category) # 리스트 타입으로 변경해서 리턴
def createxcell(self): # 엑셀을 만들기위한 메서드
categoryList = self.categoryList()
ord_sheet_name = self.wb.sheetnames
for sheetname in categoryList: # 카테고리명을 하나씩 반복문에 담는다.
if sheetname not in ord_sheet_name: # 중복되는 시트명이 없다면
self.wb.create_sheet(sheetname) # 팀명별로 시트를 하나씩 만들어준다.
ws = self.wb[sheetname]
if ws.cell(row=1, column=1).value != '사진':
ws.append(['사진', '사원명', '팀명', '직급', '사번'])
ws.move_range("A2:E2", rows=-1)
# 엑셀파일의 1행1열에 값이 없을시 사진,사원명,팀명,직급,사번 이라는 헤더를 만들어준다.
try:
self.wb.remove(self.wb['Sheet']) # 엑셀파일을 처음만들면 생성되는 기본 시트를 삭제해준다
except:
pass # 없다면 패스
self.wb.save(os.path.join(target_path, '사원리스트.xlsx'))
def getFilename(self): # 사원들의 정보를 엑셀에 저장하기 위한 메서드
li = []
category = self.categoryList() # 팀명
infolist = self.infoList() # 파일리스트
for info in infolist: # 반복을위한 len값을 알아내기 위해 파일리스트의 하나씩 가져와 파일리스트의 0번 인덱스인 팀명만 빼내서 리스트에 담아준다
li.append(info[0])
for info in infolist: # 사원을 하나씩 뽑아와 if문으로 검사
if info[0] in category: # 팀명 카테고리 안에 해당 사원의 팀명이 있다면 코드를 실행
cnt = li.count(info[0]) # 해당 팀의 팀원이 몇명인지 알아내 cnt에 저장
self.ws.column_dimensions['A'].width = 18 # 증명사진이 들어갈 셀의 크기를 조정 사진이 들어갈 열은 고정이기 때문에 밖에서 선언
self.ws = self.wb[info[0]] # 해당사원이 속한 팀의 시트를 불러와준다.
image_path = os.path.join(self.current_dir, info[0] + '_' + info[1] + '_' + info[2] + '_' + info[3] + '.jpg') # 엑셀에 업로드할 jpg의 정확한path를 찾아낸다
img = Image(image_path)
img.width = 117 # 이미지크기를 조정
img.height = 156
for i in range(2, (2+cnt)): # 해당 팀의 팀원수 만큼 반복
if not self.ws.cell(row=i, column=2).value: # i번째 row에 2번째 column에 값이 없다면 실행
# 이때 이미지는 값으로 인식이 안돼기때문에 이미지가 아닌 문자열로 비교 하기위해 2번째컬럼으로 비교
self.ws.row_dimensions[i].height = 117
# 이미지가 들어갈 각셀의 높이를 설정 행은 한칸씩 내려가면서 정보를 추가해야하기 때문에 반복문 안에서 선언
self.ws.add_image(img, 'A' + str(i)) # A열의 i번째 행에 이미지를 삽입
self.ws.cell(row=i, column=2).value = info[3] # 이후 헤더에 맞춰 정보를 순서대로 입력
self.ws.cell(row=i, column=3).value = info[0]
self.ws.cell(row=i, column=4).value = info[1]
self.ws.cell(row=i, column=5).value = info[2]
break # 값이 입력이 되었다면 반복문 탈출
else: # 조건이 맞지않으면 패스
pass
self.wb.save(os.path.join(target_path, '사원리스트.xlsx')) # 엑셀파일 저장
return print('사원리스트 정리 완료') # 정상작동을 알리기위해 리턴
def makeDir(self): # 파일을 정리할 폴더를 만드는 메서드
target_path = self.current_dir # 폴더를 만들 주소를 설정
categorylist = self.categoryList() # 팀명별로 폴더를 만들기위해 팀명카테고리를 가져온다
try:
for category in categorylist: # 팀명을 하나씩 불러와 폴더를 만들어준다.
new_dir = pathlib.Path(os.path.join(target_path, category))
new_dir.mkdir(parents=True, exist_ok=True)
# 이미 폴더가 있어도 에러를 만들지 않고 넘어가기위해 exist_ok=True 설정 오류가 발생하지 않으면 null값을 반환
except: # 이미 디렉터리가 생성 되어서 디렉터리 생성에 실패했을경우 예외처리
print('이미 폴더가 생성되었습니다.')
pass
return print('폴더 생성 완료')
def moveFile(self): # 파일을 옮기기 위한 함수 생성
folders = []
categorydic = {}
categorylist = self.categoryList()
file_list = os.listdir(self.current_dir)
jpg_files = self.filelist # 옮겨질 파일들의 리스트를 변수에 선언
for item in file_list:
item_path = os.path.join(target_path, item) # 파일 또는 폴더의 절대 경로 생성
if os.path.isdir(item_path):# 파일이 아닌 폴더(dir)일 경우에만 폴더리스트에 append
folders.append(item)
for file in jpg_files:
try:
temp_list = file.split('_') # split으로 분류명 을 저장
assert temp_list[0] in categorylist
categorydic[file] = temp_list[0] # {'파일명':'분류명'} 형식으로 딕셔너리로 저장
except:
pass
for key, value in categorydic.items(): # 딕셔너리에 키와 값을 따로 하나씩 불러온다
shutil.move(self.current_dir + '/' + key, self.current_dir + '/' + value) # 해당 주소로 파일이동
return print('파일 이동 완료')
class CleanUp: # 프로그램 작동을 위한 클래스
def __init__(self, target_path):
self.target_path = target_path
self.cf = CleanFolder(self.target_path)
# 생성자가 만들어지면 CleanFolder 클래스에 targetpath를 담고 실행
choice = input('사원파일 정리를 시작 하시겠습니까?: Y/N')
try:
if choice.upper() == 'Y': # 수락을 하였으면 파일정리를 시작
self.cf.createxcell()
self.cf.getFilename()
self.cf.makeDir()
self.cf.moveFile()
elif choice.upper() == 'N':
print('작업을 취소합니다.')
else:
print('입력을 확인하세요.')
except Exception as e:
print('에러발생 :',e)# 에러가 발생했을경우 보수를 위해 에러코드를 받아준다.
run = CleanUp(target_path) # 파일정리 실행
배웠던 내용들로 재밌는 프로그램을 하나 만들어보았다.
만드는중에는 스트레스성 탈모가 올거같았는데 만들고나니 뿌듯하네
'코딩 > 과제' 카테고리의 다른 글
과제 html (0) | 2024.04.05 |
---|---|
과제 sql 파이썬을 이용한 프로그램 (2) | 2024.04.01 |
과제 4 - 파일 입출력을 이용한 단어장 만들기 (0) | 2024.03.22 |
과제 - 주민등록번호 유효검사 (0) | 2024.03.19 |
과제 - 가위 바위 보 만들기, 로또번호 추첨하기 (0) | 2024.03.19 |