Files
UtilityPole_Info/UtilPack.py
2025-09-23 20:59:17 +09:00

298 lines
8.1 KiB
Python

import os
import re
import math
import time
import rarfile
import zipfile
import shutil
import difflib
import subprocess
import UtilPack as util
m_dbgLevel = 0
listDbgStr = []
#
def IsEmptyStr(string):
return 0 == len(string.strip())
#
def GetCurrentTime():
# 현재 시간을 구하고 구조체로 변환
current_time_struct = time.localtime()
# 구조체에서 연, 월, 일, 시간, 분, 초를 추출
year = current_time_struct.tm_year
month = current_time_struct.tm_mon
day = current_time_struct.tm_mday
hour = current_time_struct.tm_hour
minute = current_time_struct.tm_min
second = current_time_struct.tm_sec
strRet = (f"{year}/{month}/{day}_{hour}:{minute}:{second}")
return strRet
#for debug
def DbgOut(strInput, bPrint = False):
strMsg = (f"{GetCurrentTime()} : {strInput}")
listDbgStr.append(strMsg)
if True == bPrint:
print(strMsg)
def printDbgMessages():
for line in listDbgStr:
print(line)
# 입력된 패스에서 부모 폴더를 찾는다. 0 은 자기자신 1은 부모, 숫자대로 위로.
def GetParentDirName(FullPath, nUp):
parts = FullPath.split(os.sep)
nTrgIdx = 0
if nUp < len(parts):
nTrgIdx = len(parts) -nUp -1
elif nUp < 0:
nTrgIdx = len(parts) - 1
else:
nTrgIdx = 0
return parts[nTrgIdx]
# os 모듈을 사용하여 자식 폴더를 반환
def GetSubDirectories(folder_path):
subdirectories = [
d for d in os.listdir(folder_path)
if os.path.isdir(os.path.join(folder_path, d))]
return subdirectories
# 입력된 경로의 자식 폴더를 찾아 반환한다.
# 반환하는 리스트는 리커시브 - 손자, 증손자 폴더까지 전부 포함한다
def GetAllSubDirectories(root_dir):
subdirectories = []
# root_dir에서 하위 디렉토리 및 파일 목록을 얻음
for dirpath, dirnames, filenames in os.walk(root_dir):
# 하위 디렉토리 목록을 반복하며 하위 디렉토리만 추출
for dirname in dirnames:
path = os.path.join(dirpath, dirname)
if True == IsFinalFolder(path):
subdirectories.append(path)
return subdirectories
def ListFileExtRcr(pathTrg, strExt):
listRet= []
# pathTrg의 하위 디렉토리 및 파일 목록을 얻음
for dirpath, dirnames, filenames in os.walk(pathTrg):
for file in filenames:
extTmp = GetExtStr(file, False)
if extTmp.lower() == strExt and file.startswith('.'):
listRet.append(os.path.join(dirpath, file))
return listRet
# 입력된 경로가 자식 폴더를 가지고 있는지 판단한다.- 최종 폴더인지 여부
# 자식이 없으면 True, 자식이 있으면 False
def IsFinalFolder(path):
bRet = True
contents = os.listdir(path)
for item in contents:
if True == os.path.isdir(item):
bRet = False
break
return bRet;
# 어떤 경로 안에서 특정 확장자의 파일을 뽑아내어 그 리스트를 반환한다.
def FindFileFromExt(path, ext):
bDot = False
if 0 <= ext.find('.'):
bDot = True
listRet = []
if False == os.path.exists(path):
return listRet
contents = os.listdir(path)
for item in contents:
if True == os.path.isdir(item):
continue
extItem = GetExtStr(item, bDot)
if extItem.lower() == ext.lower():
listRet.append(item)
return listRet
# 파일 이름에서 확장자를 뽑아낸다. True : '.' 을 포함한다.
def GetExtStr(file_path, bDot = True):
retStr = ""
# 파일 경로에서 마지막 점을 찾아 확장자를 추출
last_dot_index = file_path.rfind('.')
if last_dot_index == -1:
retStr = "" # 점이 없는 경우 확장자가 없음
else:
if True == bDot:
retStr = file_path[last_dot_index:]
else:
retStr = file_path[last_dot_index+1:]
return retStr
# 문자열에 포함된 단어를 지운다.
def RmvSubString(mainString, subString):
# 문자열에서 부분 문자열의 인덱스를 찾습니다.
strIdx = mainString.find(subString)
if strIdx == -1: # 부분 문자열이 존재하지 않으면 그대로 반환합니다.
return mainString
endIdx = strIdx + len(subString)
# 부분 문자열을 제거하고 새로운 문자열을 반환합니다.
return mainString[:strIdx] + mainString[endIdx:]
def ExtractZIP(zip_file, extract_to):
with zipfile.ZipFile(zip_file, 'r') as zf:
zf.extractall(extract_to)
#
def CreateZIP(output_zip, *files):
with zipfile.ZipFile(output_zip, 'w') as zf:
for file in files:
pathTemp = os.path.join('root', os.path.basename(file))
zf.write(file, pathTemp)
bRet = False
if os.path.exists(output_zip):
bRet = True
return bRet
# 파일 리스트에 들어있는 파일만 골라서 압축을 합니다. 상대경로를 제거하는게 기본값.
def CreateZIPShell(zipName, *files, bRmvRPath = True):
command = "zip "
if True == bRmvRPath:
command += "-j "
command += f"\"{zipName}\" "
# 이중 리스트인 이유를 모르겠다.
for file in files:
strTemp = ""
if isinstance(file, list):
strTemp = ' '.join(file)
else:
strTemp = f"\"{file}\" "
command += strTemp
# for item in file:
# command += f"\"{item}\" "
result = subprocess.run(command, shell=True,
capture_output=True, text=True)
bRet = False
if 0 == result.returncode:
bRet = True
return bRet
# 특정 확장자만 쉘을 이용해서 압축한다
def CreateZIPShExt(zipName, TrgExt):
command = f"zip -j {zipName} *.{TrgExt}"
result = subprocess.run(command, shell=True, capture_output=True, text=True)
bRet = False
if 0 == result.returncode:
bRet = True
return bRet
# JSON 을 트리 구조로 출력한다.
def PrintJSONTree(data, indent=0):
if isinstance(data, dict):
for key, value in data.items():
print(' ' * indent + str(key))
PrintJSONTree(value, indent + 1)
elif isinstance(data, list):
for item in data:
PrintJSONTree(item, indent)
else:
print(' ' * indent + str(data))
# 세로 크기를 가로 비율대로 줄여서 반환 (가로를 기준으로 세로 길이)
def GetRSzHeight(nWidth, nHeight, nTrgW):
if nWidth <= 0 or nTrgW <= 0:
return 0;
fRatio = nTrgW / nWidth
nTrgH = round(nHeight * fRatio)
return nTrgH
# 가로 크기를 세로 비율대로 줄여서 반환 (세로를 기준으로 가로 길이)
def GetRSzWidth(nWidth, nHeight, nTrgH):
if nHeight <= 0 or nTrgH <= 0:
return 0;
fRatio = nTrgH / nHeight
nTrgW = round(nWidth * fRatio)
return nTrgW
# 엑셀 열 너비는 약 7.5픽셀 단위
# 엑셀 행 높이는 약 25픽셀 단위
# 이대로는 사이즈가 안 맞아서 적당히 곱해줌
def GetCellSize(nImgW, nImgH, DPI = 96):
column_width = (nImgW / DPI) * 7.5 * 2
row_height = (nImgH / DPI) * 25 * 3
return column_width, row_height
def GetSheetInfoValue(text):
if text is None:
return "", ""
pattern = r'<(.*?)>'
matches = re.findall(pattern, text)
cleaned = re.sub(pattern, '', text)
return cleaned, matches
# 두 GPS 좌표 간 거리 구하기 (미터)
def GetDistanceGPS(lat1, lon1, lat2, lon2):
# 지구의 반지름 (단위: 미터)
R = 6371008.8
# 위도와 경도를 라디안으로 변환
lat1 = math.radians(lat1)
lon1 = math.radians(lon1)
lat2 = math.radians(lat2)
lon2 = math.radians(lon2)
# 차이 계산
dlat = lat2 - lat1
dlon = lon2 - lon1
# Haversine 공식 적용
a = math.sin(dlat / 2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2)**2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
# 거리 계산
distance = R * c
return distance