태그 보관물: python

[Python] 56-Powerful digit sum

A googol (10100) is a massive number: one followed by one-hundred zeros; 100100 is almost unimaginably large: one followed by two-hundred zeros. Despite their size, the sum of the digits in each number is only 1.

Considering natural numbers of the form, ab, where a, b < 100, what is the maximum digital sum?


문제 해결 전략

  1. 제곱을 문자열로 변환하여 문자열을 한자씩 더해 간다.
  2. 문자열을 더하기 위해서 reduce 와 lambda를 활용한다.
def sumOfDigit(i, j):
  powValue = str(i**j)
  result = reduce(lambda x, y: int(x)+int(y), powValue)
  return int(result)


if __name__ == '__main__':
  maxValue = iVal = jVal = 0    
  for i in range(1, 101):      
    for j in range(1, 101):        
      result = sumOfDigit(i, j)
      if (result > maxValue):          
        maxValue, iVal, jVal = result, i, j          
  print "i=%d, j=%d, maximum=%d" % (iVal, jVal, maxValue)

PythonMagick과 PIL을 이용한 PDF에서 이미지 추출

테스트 환경

  • 운영체제: Windows 7 64Bit
  • PythonVersion: 2.7

ImageMagick 설치

  1. ImageMagick 다운로드 [링크]
  2. ImageMagick 설치
  3. 중요 환경 변수 등록 (IMAGEMAGICK_HOME)

PythonMagick 설치

PIP 또는 easy_install 을 이용하여 설치 할 수 없기 때문에 수동으로 설치를 해야 하는 부분이 있습니다.

  1. PythonMagick‑0.9.10‑cp27‑none‑win32.whl 파일 다운로드 [링크] (운영체제가 64Bit여도 32Bit 파일을 다운로드)
  2. pip 를 이용하여 설치
C:UserscoozplzDownloads>pip install PythonMagick-0.9.10-cp27-none-win32.whl

테스트
파이썬 명령 프롬프트에서 import를 했을때 Module Not Found 가 표시되지 않으면 정상적으로 설치된 것입니다.

>>> import PythonMagick

GhostScript 설치

GhostScript가 없는 경우 Windows에서 실행하면 파일의 저장경로를 찾을 수 없다는 오류가 발생됩니다.

  1. GhostScript 32Bit 다운로드 [링크] (운영체제가 64Bit여도 32Bit 파일을 다운로드)
  2. GhostScript 설치
  3. 환경변수 등록 (GHOSTSCRIPT_HOME)

PIL 설치

> easy_install PIL

테스트
파이썬 명령 프롬프트에서 import를 했을때 Module Not Found 가 표시되지 않으면 정상적으로 설치된 것입니다.

>>> import Image

소스

import PythonMagick
import Image
import time

def loadPDFImage(pdfPath, outputFile):
    """
    PDF 파일을 로딩하여 이미지 파일로 저장한다.
    :param pdfPath  PDF 파일 경로
    :param outputFile   추출한 이미지 저장 경로
    """
    pdfImage = PythonMagick.Image()
    pdfImage.density("300")
    pdfImage.read(pdfPath)
    pdfImage.write(outputFile)


def splitImage(imageFileName, splittedImageSavingDir):
    """
    이미지 파일을 원하는 크기로 Split한 후 저장한다.
    :param imageFileName    원본 이미지의 경로
    :param splittedImageSavingDir   잘린 이미지를 저장할 상위 디렉토리
    """
    loadedImage = Image.open(imageFileName)
    for i in range(3):
        left = 256 + (952 * i) + (15 * i)
        right = 1212 + (952 * i) + (15 * i)
        cropImage = loadedImage.crop((left, 278, right, 1800))
        savingFileName = "%s_%d.jpg" % (time.strftime('%Y%m%d%H%M'), i)
        cropImage.save("%s/%s" % (splittedImageSavingDir, savingFileName))
        print "Successfully saved, %s" % savingFileName


if __name__ == '__main__':
    pdfPath = "D:/test.pdf"
    outputPath = "D:/test.jpg"
    splittedImageSavingDir = "D:/"
    loadPDFImage(pdfPath, outputPath)
    splitImage(outputPath, splittedImageSavingDir)

결과

원본 PDF
ORIGIN_IMAGE

잘린 이미지
SPLIT_IMAGE{max-width:320px}

Python 스크립트파일을 Exe로 변경

Install py2exe

> pip install py2exe

실행 스크립트

#execute_test.py
print 'HelloWorld'

Setup.py 스크립트

#setup.py
from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

options = {
    "bundle_files": 1,                    # create singlefile exe
    "compressed"  : 1,                    # compress the library archive
    "excludes"    : ["w9xpopen.exe"]    # we don't need this
}

setup(
    options = {'py2exe' : options},
    windows = [{'script': "merge_swf_helper.py"}],
    zipfile = None,
)

Cmd 창에서 빌드 명령 실행

> python setup.py install

결과 확인

명령을 실행한 폴더의 dist 디렉토리에 들어가면 생성된 exe 파일을 볼 수 있다.

[Python] Read excel(xlsx)

xlrd 를 이용한 엑셀 파일 읽기


기능

xlsx 파일에서 cell에 입력된 Text 데이터를 모두 출력한다. 출력 포맷은 excel 데이터와 동일하게 출력하도록 한다. (ROW별로 출력)

리소스정보

  • 입력: 컨텐츠가 포함된 xlsx 파일(resource.xlsx)

소스코드
#-*- coding: utf-8 -*-
# ================================================
# Author: coozplz@gmail.com
# Date: 2015. 08. 11
# Desc: 토플 앱 개발에 필요한 엑셀 파일 분석
# ================================================

import xlrd

def open_excel(path):
    '''
    엑셀 파일에 포함된 내용을 system.out으로 출력한다. 
    '''
    workbook = xlrd.open_workbook(path)

    # 엑셀 시트 개수 정보 출력
    print workbook.nsheets
    # 0번 시트정보를 조회한다.
    sheet = workbook.sheet_by_index(0)
    for row_num in range(sheet.nrows):
        row = sheet.row(row_num)
        cols = []
        for cell in row:
            if (cell.ctype == 1):
                cols.append(cell.value)
        print ','.join(cols)

#
# Main
#
if __name__ == '__main__':
    path = './word_end_0811.xlsx'
    open_excel(path)

[ST3] Python 개발환경 설정하기

Sublime Text 3(ST3) Python 개발환경 설정하기

맥에서 사용하는 Sublime Text 3 를 파이썬 개발 환경으로 사용하기 위한 설정에 대해 정리

ST3 다운로드 및 인스톨

다운로드

패키지 인스톨러 설치

다운로드

링크 생성

$ sudo ln -s /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl /usr/bin/subl

테마 다운로드

인스톨 패키지를 이용하여 설치.

  • Flatland

환경설정

사용자 설정

경로: Preferences > Settings – User

{
  "auto_complete": false,
  "auto_complete_commit_on_tab": true,
  "auto_match_enabled": true,
  "bold_folder_labels": true,
  "caret_style": "solid",
  "color_scheme": "Packages/Theme - Flatland/Flatland Dark.tmTheme",
  "detect_indentation": true,
  "draw_indent_guides": true,
  "ensure_newline_at_eof_on_save": true,
  "file_exclude_patterns": [
    "*.DS_Store",
    "*.pyc",
    "*.git"
  ],
  "find_selected_text": true,
  "fold_buttons": false,
  "folder_exclude_patterns": [],
  "font_face": "Menlo",
  "font_options": [
    "no_round"
  ],
  "font_size": 13,
  "highlight_line": true,
  "highlight_modified_tabs": true,
  "ignored_packages": [
    "Vintage"
  ],
  "indent_to_bracket": true,
  "line_padding_bottom": 0,
  "line_padding_top": 0,
  "match_brackets": true,
  "match_brackets_angle": false,
  "match_brackets_braces": true,
  "match_brackets_content": true,
  "match_brackets_square": true,
  "new_window_settings": {
    "hide_open_files": true,
    "show_tabs": true,
    "side_bar_visible": true,
    "status_bar_visible": true
  },
  "remember_open_files": true,
  "remember_open_folders": true,
  "save_on_focus_lost": true,
  "scroll_past_end": false,
  "show_full_path": true,
  "show_minimap": false,
  "tab_size": 2,
  "theme": "Flatland Dark.sublime-theme",
  "translate_tabs_to_spaces": true,
  "trim_trailing_white_space_on_save": true,
  "use_simple_full_screen": true,
  "vintage_start_in_command_mode": false,
  "wide_caret": true,
  "word_wrap": true
}

Python 환경 설정

  • 경로: Preferences > Settings – User 설정 파일 위치와 동일한 위치
  • 파일명: Python.sublime-settings
 
{
 "draw_white_space": "all",
 "auto_indent": true,
 "rulers": [
 79
 ],
 "smart_indent": true,
 "tab_size": 4,
 "trim_automatic_white_space": true,
 "use_tab_stops": true,
 "word_wrap": true,
 "wrap_width": 80
}

플러그인 설치

SideBarEnhancements
Anacoda
  • Lint 제거Preferences > Package Setting > Anaconda > User – Setting {“anaconda_lint” : false}
  • 단축키
    • Goto Definition: ctrl + alt + g
    • Find Usages : ctrl + alt + f
    • Get Documentation: ctrl + alt + d
SublimeLinter-pep8 and SublimeLinter-pyflakes
GitGutter
SublimeREPL
  1. 단축키 생성 방법
    1. SublimeREPL.sublime-build 파일 생성
      경로: ~/Application Support/Sublime Text 3/Packages/User
    2. SublimeREPL.sublime-build 설정 내용 추가
    3. {
          "target": "run_existing_window_command", 
          "id": "repl_python_run",
          "file": "config/Python/Main.sublime-menu"
      }
      
    4. command + b 빌드 결과 출력 여부 확인
  • 단축키
    • Goto Definition: ctrl + alt + g
    • Find Usages : ctrl + alt + f
    • Get Documentation: ctrl + alt + d
 

참조링크

[Python] 폴더내 파일명 일괄 변경

폴더내 파일명 일괄 변경


개발내용

플래시 컨텐츠 테스트를 위해 폴더내 파일명을 특정 패턴에 맞게 일괄로 변경해야 되는 이슈가 있어 개발.

개발환경

  • Language: Python 2.7.10
  • OS: Windows 7 64bit

소스코드
#-*- coding: utf-8 -*-
# ===============================================================
# Author: coozplz@gmail.com
# File: flash_korean_file_rename.py
# Date: 2015. 07. 14
# Desc: 플래시 샘플 컨텐츠들의 이름을 변경하기 위한 프로그램.
# ===============================================================

import os

def rename_flash_content(path, key, startIndex):
	'''
	플래시 샘플 컨테츠의 이름을 변경한다.
	:param path 루트 디렉토리 경로
	:param key 컨텐츠 구분값(명사: N, 형용사: A, 동사: V, 인사말:G)
	:param startIndex 컨텐츠 시작 번호
	'''
	print 'path=%s' % path
	minValue = i = startIndex;
	j = 1

	for item in os.listdir(root):
		# 파일명과 확장자를 분리한다.
		# item: 493-A023-c.swf
		# filename: 493-A023-c
		# file_extension: .swf
		filename, file_extension = os.path.splitext(item)

		if (file_extension != '.swf'):
			print 'invalid file name %s' % item
			continue;

		# item의 절대 경로를 구한다.
		fullpath = os.path.join(root, item)

		mod = j % 4
		suffix = 'a'
		if mod == 1:
		suffix = 'b'
		elif mod == 2:
		suffix = 'c'
		elif mod == 3:
		suffix = 'd'
		else:
		suffix = 'a'

		# 변경할 이름의 포맷을 정의한다.
		renamed_file_name = "%d-%s%03d_%s.swf" % (i, key, i - minValue + 1, suffix)
		if (key == 'NUM'):
			renamed_file_name = "%d-%s%02d_%s.swf" % (i, key, i - minValue + 1, suffix)
		#endif	
		if (j % 4 == 0):
			i = i+1
			j=j+1
			rename_full_path = os.path.join(root, renamed_file_name)
			os.rename(fullpath, rename_full_path)
			print '%s is rename to %s' % (item, renamed_file_name)
		#end - if
	#end - for	
if __name__ == '__main__':
	root = "D:/git/flash_korean_novice/resources/ai/verb"
	key = 'V'
	startIndex=321
	print root
	rename_flash_content(root, key, startIndex)
#end-if	

[Python] AndroidLint result to CSV

최근 개발 도구를 JetBrain 라인의 제품을 사용하고 있습니다.

Android는 AndroidStudio를 이용해서 하고 Java는 IntelliJ를 이용하고 Python은 PyCharm을 이용해서 하고 있습니다.

같은 회사의 제품을 사용하니 단축키를 동일하게 할 수 있어 좋습니다.
물론 Android Studio에서 Eclipse 단축키를 제공하기는 하지만 저는 그냥 단축키를 바꾸는 편을 선호 합니다.

예전에 PC방에 가도 단축키를 모두 바꿔서 적응하면 게임방을 옮길때마다 변경해줘야 하는 불편함이 있어서 몸에 벤 방식이 기본을 그대로 사용하고 있습니다. (많이 불편하면 변경을 합니다.)

잡설은 빼고… 어쨌든 정적 분석도구를 이용해서 분석한 후 Export를 하려고 하니 HTML, XML 두가지 방식을 지원합니다. XML로 저장 후 Excel로 읽을려고 하니 안될꺼 같아. 내용만 뽑아 CSV형태로 저장하는 방식으로 했습니다.

[Problem]
AndroidStudio에서 Lint를 이용해 분석된 XML 결과를 Excel로 보고싶다.

[Solution]
XML을 파싱해서 분석 후 CSV 형태로 저장하자.

[Review]
너무 간단하게 파싱이 되서 당황했습니다. 지금은 Java로 작성하는게 훨씬 편한거 같은데 python이 익숙해지면 훨씬 쉽게 작성할 수 있을 것 같습니다.
그리고 Linux에서는 python을 기본으로 제공해주니 별도의 설치도 필요 없습니다.(Python3는 별도로 설치해야함)

"""
# AndroidLintParser.py
# Author: coozplz@gmail.com
# Date: 2014. 08. 06
# Desc: Parse android stuidio's code analyze result(xml) to csv.
# usage: AndroidLintParser.py [-h] input output
    positional arguments:
      input       Android lint export path
      output      Output csv path
# Input:
<problems>
    <problem>
        <file>....</file>
        <line>9</line>
        <module>...</module>
        <package>...</package>
        <entry_point TYPE="field" FQNAME="..." />
        <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">
                                    Declaration can have final modifier
        </problem_class>
        <hints />
        <description>Declaration can have final modifier</description>
  </problem>
</problems>
# Output:
=============================================================
    SEVERITY, MODULE, PACKAGE, FILE_NAME, LINE, DESC
=============================================================
"""
from xml.etree.ElementTree import parse
from xml.sax.saxutils import unescape
from os import listdir
from os import path
import argparse
import sys
'''
# 입력 파라미터를 설정한다.
'''
parser = argparse.ArgumentParser()
parser.add_argument("input", help="Android lint export path", type=str)
parser.add_argument("output", help="Output csv path", type=str)
args = parser.parse_args()

# 사용자가 input path의 마지막에 '/' 를 붙이지 않을 수도 있기 임의로 붙여준다.
# 두개를 붙여도 상관은 없다
XML_INPUT = args.input+"/"
CSV_OUTPUT = args.output


def parse_android_lint_to_csv(element):
    """
    AndroidLint 의 Problem Tag 를 분석하여 원하는 값을 추출한다.
    :param element: Problem Element
    :return: output String
    """
    filename = element.findtext("file")
    filename = filename[filename.rfind("/")+1:]
    entry_point = element.find("entry_point").get("FQNAME")
    entry_point = entry_point.split(' ')
    if len(entry_point) > 1:
        entry_point = entry_point[1]
    line = element.findtext("line")
    module = element.findtext("module")
    package = element.findtext("package")
    severity = element.find("problem_class").get("severity")
    desc = unescape(element.findtext("description"))
    if severity == "TYPO" or severity is "None":
        return
    return "{0},{1},{2},{3},{4},{5},{6}\n".format(severity,
                                                  module,
                                                  package,
                                                  filename,
                                                  entry_point,
                                                  line,
                                                  desc)


'''
#Main
'''
try:

    f = open(CSV_OUTPUT, "w")
except IOError:
    print('cannot open', CSV_OUTPUT)
else:
    try:
        # 제외 파일명 저장용 배열
        exceptFiles = []
        # 제외된 파일의 개수
        exceptFileCount = 0
        # 총 파일의 개수
        count = 0
        for iterFileName in listdir(XML_INPUT):
            count += 1
            if iterFileName.lower().find(".xml") < 0:
                '''
                # 파일명이 Xml 형식이 아닌것은 제외 목록에 추가하고 처리하지 않는다.
                '''
                exceptFileCount += 1
                exceptFiles.append(iterFileName)
                continue
            xmlDoc = parse(XML_INPUT + iterFileName)
            problems = xmlDoc.getroot()
            for parent in problems:
                data = parse_android_lint_to_csv(parent)
                if data:
                    # 데이터가 있는 경우에만 파일에 쓴다
                    f.write(data)
    except IOError as ioE:
        print("I/O error: {0}".format(ioE))
    except ValueError as ve:
        print("Could not convert data: {0}".format(ve))
    except:
        print("UnExpected error", sys.exc_info()[0])
        raise
finally:
    # 파일은 반드시 닫는다
    f.close()


# 결과를 출력
print("TOTAL={0}".format(count))
print("OUTPUT_FILE_NAME={0}".format(CSV_OUTPUT))
print("OUTPUT_FILE_SIZE=%0.2f KBytes" % (path.getsize(CSV_OUTPUT) / 1024))
if exceptFileCount > 0:
    print("EXCEPT={0}, EXCEPT_FILES={1}".format(exceptFileCount,
                                                exceptFiles))