이 블로그 검색

2015년 11월 5일 목요일

Unicode With Python - 유니코드와 파이썬

Ascii code (American Standard Code for Information Interchange, 미국 정보 교환 표준 부호)

7비트 글자 인코딩으로, 000(0x00)부터 127(0x7F)까지 총 128개의 부호가 사용된다. 1바이트를 구성하는 8비트 중에서 7비트만 쓰도록 제정된 이유는, 나머지 1비트를 통신 에러 검출을 위해 사용하기 때문이었다.


Unicode

ascii 만으로는 전 세계의 모든 문자를 한번에 다룰수 없었기 때문에 등장한 방식으로 멀티바이트를 사용한다. 한글완성형(euc-kr) 인코딩은2바이트를 사용하지만 유니코드는 아니다. 

UCS, UTF-8, UTF-16 등은 인코딩 방식의 종류이며 유니코드를 처리하는 알고리즘을 일컫는다 (일종의 압축과 같은것). 인코딩에 따라 문자하나를 고정된 멀티바이트로 표현하거나 영어는 1바이트로 처리하고 나머지는 멀티바이트로 처리할수도 있고 유동적인 바이트를 사용해 표현할수도 있다. 또한 문자하나의 바이트순서에 따라 리틀엔디안(utf-16-le), 빅엔디안(utf-16-be)으로 구분되기도하며 utf-16 인코딩과는 다른것이다.

중요한 점은 UTF-8 문자열이 유니코드를 표현하는(압축) 한가지 방식일뿐 유니코드 자체는 아니라는 점은 헷갈리기 쉬우니 제대로 알아 두어야 한다.


encoding (인코딩) : 유니코드를 어떤방식으로 처리(압축)할지를 말한다. UTF-8, UTF-16, UTF-16-LE등등 인코딩 방식에 따라 다르게 저장된다.


decoding (디코딩) : UTF-8, UTF-16, UTF-16-LE 등과 같이 압축된 문자열을 유니코드로 압축을 푸는것을 뜻한다.


유니코드를 바이트로 출력

>>> [hex(ord(x)) for x in u"한글"]

['0xd55c', '0xae00']


인코딩된 유니코드를 바이트로 출력

>>> [hex(ord(x)) for x in u"한글".encode('utf-8')]

['0xed', '0x95', '0x9c', '0xea', '0xb8', '0x80']


>>> [hex(ord(x)) for x in u"한글".encode('utf-16')]

['0xff', '0xfe', '0x5c', '0xd5', '0x0', '0xae']


>>> [hex(ord(x)) for x in u"한글".encode('utf-16-le')]

['0x5c', '0xd5', '0x0', '0xae']


>>> [hex(ord(x)) for x in u"한글".encode('utf-16-be')]

['0xd5', '0x5c', '0xae', '0x0']


>>> [hex(ord(x)) for x in u"한글".encode('euc-kr')]

['0xc7', '0xd1', '0xb1', '0xdb']



Unicode With Python - 유니코드와 파이썬


* 유니코드로 변환하기

우리가 보통 사용하는 문자열은 str타입이다. 간단하게 문자열 앞에 u를 붙히거나 unicode 함수를 통해서 유니코드로 변화할수 있다. 즉 unicode 함수는 문자열이 유니코드로 decoding됨을 의미한다. 반대로 얘기하면 str은 인코딩이 되어있는 뜻이 되며 기본적으로는 ascii로 인코딩 되어있는 것이다.


>>> type("text") # string

<type 'str'>


>>> type(u"text") # convert string to unicode

<type 'unicode'>


>>> type(unicode("text")) # convert string to unicode

<type 'unicode'>



* 유니코드로 코딩하기

temp.py 파일을 하나 만들고  아래와 같이 저장한 후 실행해보자.


var =  "한글"


헉!! 그저 변수에 한글을 입력했을 뿐인데 아래와 같이 에러가 발생하고 만다.. 

왜일까? Python의 기본 인코딩은 ascii로 되어 있기 때문에 ascii코드 이외의 문자로 코딩을 하게 되면 파이썬 해석기가 코드를 해석하지 못하고 에러를 토해내게 된다.


SyntaxError: Non-ASCII character '\xed' in file temp.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details



한글등과 같이 유니코드를 프로그래밍에서 다루기 위해서 아래와 같은 주석문을 파일최상단에 추가해주자. 자주 사용되니 꼭 외워두자.


#_*_ coding:utf-8 _*_

var =  "한글"



*  시스템 기본 인코딩


앞서 말했듯이 Python의 시스템 기본인코딩은 ascii이다. 백문이 불여일견 확인해보자!


>>> import sys

>>> print sys.getdefaultencoding()

ascii


시스템 인코딩이 ascii이면 어떠한 문제가 발생하는지 한가지 테스트를 해보자.


#_*_ coding:utf-8 _*_

print unicode("한글")


문자열을 유니코드로 바꾸었더니 아래와 같은 에러를 출력하고 만다.

unicode(str) 함수는 인코딩된 문자열을 입력으로 받아서 디코딩을 거쳐 유니코드로 변환하는 작업을 한다. 시스템 인코딩이 ascii로 되어있기 떄문에 문자열이 7비트의 최대값인 127(0x7f)을 넘어가면 오류가 발생하게 된다. ( ascii로 표현된 문자열 '한글'은  ['0xed', '0x95', '0x9c', '0xea', '0xb8', '0x80'] 이다. )


Traceback (most recent call last):

  File "temp.py", line 2, in <module>

    print unicode("한글")

UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 0: ordinal not in range(128)



아래와 같이 sys.setdefaultencoding함수로 시스템 인코딩을 UTF-8로 변경후 다시 시도해보자.

!! 주의 : reload(sys)를 실행하지 않으면 setdefaultencoding 함수를 실행할수 없다. 꼭 기억하자!


#_*_ coding:utf-8 _*_

import sys

reload(sys)

sys.setdefaultencoding('utf-8')

print unicode("한글")


에상대로 별다른 오류없이 유니코드로 변환되어 잘 출력되었다.


한글



sys.setdefaultencoding('utf-8') 함수의 장점은 일반 문자열을 유니코드로 디코딩시 unicode 함수를 사용할수 있다는 점이다. 수많은 문자열 앞에 u를 붙이는 것은 힘든일이 될수도 있기 때문이다.



* 인코딩된 유니코드 파일 열기


유니코드 파일을 인/디코딩 하기위한 io, codecs 모듈 두가지가 있으며 파일을 열고 닫는 함수나 사용법은 기본 라이브러리에 포함됨 open, write, writelines, read, close등 모두 같다.

!! unicode("한글")은 u"한글"로 대체해도 똑같다. 단, unicode함수안에 한글을 넣으려면 sys.setdefaultencoding에 utf-8과 같이 유니코드 인코딩이 설정되어 있어야만 한다.


#_*_ coding:utf-8 _*_

import sys

reload(sys)

sys.setdefaultencoding('utf-8')


# io 모듈

import io

# Encoding Unicode to UTF-8

with io.open("filename.txt", "w", encoding='utf-8') as f:

    f.writelines(unicode("한글"))


# Decoding UTF-8 to Unicode

with io.open("filename.txt", "r", encoding='utf-8') as f:

    print f.read()



# codecs 모듈

import codecs


# Encoding Unicode to UTF-16

with codecs.open("filename.txt", "w", encoding='utf-16') as f:

    f.writelines(unicode("한글"))


# Decoding UTF-16 to Unicode

with codecs.open("filename.txt", "r", encoding='utf-16') as f:

    print f.read()

2015년 10월 26일 월요일

Haskell Package 지우기

하스켈을 하다보면 패키지 이름이 겹치는 경우가 있다. 그럴경우 사용하지 않는 한가지를 아래와 같이 처리한다.

ghc-pkg unregister --force 패키지이름
ex) ghc-pkg unregister --force regex-compat-0.95.1

Haskell - Not in scope: 'pure'

ghci> :t pure
<interactive>:1:1: Not in scope: pure
ghci> :m +Control.Applicative
ghci> :t pure
pure :: Applicative f => a -> f a

2015년 10월 19일 월요일

Blender tip #30: Changing Modifier Settings on Multiple Objects at Once

Sometimes, when you’re working on a scene that has lots of different objects with modifiers on it, you might want to change a specific modifier setting on several objects at once (like the Subdivision Surface modifier for instance). Luckily, Blender has a cool little feature that enables you to do just that.
(A) Select all the objects with the same Modifier that you want to change.
(B) Go to the modifiers panel and locate the modifier (in this case the Subdivision Surface modifier).
(C) Simply hold down the ALT key while changing any value, and the changes will be assigned to all of the other selected objects that have the same modifier.

2015년 9월 22일 화요일

Python Interpreter For Android - REPL

Link : https://play.google.com/store/apps/details?id=enurisoft.com.pythoninterpreter

 Python Interpreter For Android

It is Python interpreter for Android.
It is Python REPL.
It offers a great learning experience for Python beginners.
It is written in python using the Kivy framework. (http://kivy.org)


 Python Interpreter For Android- 스크린샷 미리보기 이미지   Python Interpreter For Android- 스크린샷 미리보기 이미지

2015년 9월 9일 수요일

Kivy - Buildozer 각종 오류 해결하기

1. kivy 1.9.0 버전을 buildozer로 apk를 만들경우 몇가지 버전을 맞추어주어야 한다.

cython 0.21
android build tool revision 22.0
pygments 설치
ant 1.9.3

2. buildozer.spec 파일에 pygments와 같은 추가 모듈이 있는 경우 available module 목록에 없다며 에러를 뱉어내는 경우가 있다.
아래와 같이 python 가상환경을 실행후 buildozer android debug or release를 다시 실행해주면 빌드가 된다.

virtualenv --python=python2.7 ./venv

2015년 9월 8일 화요일

Kivy - Buildozer로 Android APK 만들기

가장먼저 buildozer install하기
git clone https://github.com/kivy/buildozer.git
cd buildozer
sudo python2.7 setup.py install

인스톨이 완료되면 초기화를 실행한다.
buildozer init

init를 완료하고 나면 buildozer.spec 파일이 생성되는데  정보를 적절하게 입력해준다.


[app]

# (str) Title of your application
title = Kivy Python Interpreter

# (str) Package name
package.name = KivyPythonInterpreter

# (str) Package domain (needed for android/ios packaging)
package.domain = enurisoft.com

# (str) Source code where the main.py live
source.dir = /home/mataeoh/Work/PythonProject/Kivy/ScrollBar

# (list) Source files to include (let empty to include all the files)
source.include_exts = ttf,py,png,jpg,atlas,kv

# (list) Source files to exclude (let empty to not exclude anything)
#source.exclude_exts = spec

# (list) List of directory to exclude (let empty to not exclude anything)
#source.exclude_dirs = tests, bin

# (list) List of exclusions using pattern matching
#source.exclude_patterns = license,images/*/*.jpg

# (str) Application versioning (method 1)
#version.regex = __version__ = '(.*)'
#version.filename = %(source.dir)s/main.py

# (str) Application versioning (method 2)
version = 1.2.0

# (list) Application requirements
# comma seperated e.g. requirements = sqlite3,kivy
requirements = kivy

# (str) Custom source folders for requirements
# Sets custom source for any requirements with recipes
# requirements.source.kivy = ../../kivy

# (list) Garden requirements
#garden_requirements =

# (str) Presplash of the application
#presplash.filename = %(source.dir)s/data/presplash.png

# (str) Icon of the application
#icon.filename = %(source.dir)s/icon/kivy-icon-128.png

# (str) Supported orientation (one of landscape, portrait or all)
orientation = portrait

# (bool) Indicate if the application should be fullscreen or not
fullscreen = 1


#
# Android specific
#

# (list) Permissions
#android.permissions = INTERNET

# (int) Android API to use
#android.api = 14

# (int) Minimum API required (8 = Android 2.2 devices)
#android.minapi = 8

# (int) Android SDK version to use
#android.sdk = 21

# (str) Android NDK version to use
#android.ndk = 9c

# (bool) Use --private data storage (True) or --dir public storage (False)
#android.private_storage = True

# (str) Android NDK directory (if empty, it will be automatically downloaded.)
#android.ndk_path =

# (str) Android SDK directory (if empty, it will be automatically downloaded.)
#android.sdk_path =

# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
#android.p4a_dir =

# (list) python-for-android whitelist
#android.p4a_whitelist =

# (str) Android entry point, default is ok for Kivy-based app
#android.entrypoint = org.renpy.android.PythonActivity

# (list) List of Java .jar files to add to the libs so that pyjnius can access
# their classes. Don't add jars that you do not need, since extra jars can slow
# down the build process. Allows wildcards matching, for example:
# OUYA-ODK/libs/*.jar
#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar

# (list) List of Java files to add to the android project (can be java or a
# directory containing the files)
#android.add_src =

# (str) python-for-android branch to use, if not master, useful to try
# not yet merged features.
#android.branch = master

# (str) OUYA Console category. Should be one of GAME or APP
# If you leave this blank, OUYA support will not be enabled
#android.ouya.category = GAME

# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png

# (str) XML file to include as an intent filters in <activity> tag
#android.manifest.intent_filters =

# (list) Android additionnal libraries to copy into libs/armeabi
#android.add_libs_armeabi = libs/android/*.so
#android.add_libs_armeabi_v7a = libs/android-v7/*.so
#android.add_libs_x86 = libs/android-x86/*.so
#android.add_libs_mips = libs/android-mips/*.so

# (bool) Indicate whether the screen should stay on
# Don't forget to add the WAKE_LOCK permission if you set this to True
#android.wakelock = False

# (list) Android application meta-data to set (key=value format)
#android.meta_data =

# (list) Android library project to add (will be added in the
# project.properties automatically.)
#android.library_references =

#
# iOS specific
#

# (str) Name of the certificate to use for signing the debug version
# Get a list of available identities: buildozer ios list_identities
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"

# (str) Name of the certificate to use for signing the release version
#ios.codesign.release = %(ios.codesign.debug)s


[buildozer]

# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2

# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
warn_on_root = 1


#    -----------------------------------------------------------------------------
#    List as sections
#
#    You can define all the "list" as [section:key].
#    Each line will be considered as a option to the list.
#    Let's take [app] / source.exclude_patterns.
#    Instead of doing:
#
#[app]
#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
#
#    This can be translated into:
#
#[app:source.exclude_patterns]
#license
#data/audio/*.wav
#data/images/original/*
#


#    -----------------------------------------------------------------------------
#    Profiles
#
#    You can extend section / key with a profile
#    For example, you want to deploy a demo version of your application without
#    HD content. You could first change the title to add "(demo)" in the name
#    and extend the excluded directories to remove the HD content.
#
#[app@demo]
#title = My Application (demo)
#
#[app:source.exclude_patterns@demo]
#images/hd/*
#
#    Then, invoke the command line with the "demo" profile:
#
#buildozer --profile demo android debug


디버그로 APK 빌드하기
buildozer android debug

릴리즈로 빌드하기
buildozer android release

Instructions for creating a signed, release APK, suitable for the Google Play Store

Fields

  • my-project - The directory for your project
  • my-new-key - The name of the key you generate
  • my-alias - A short alias name for the key
  • MyProject - The name of your project, and APK
  • version - The version of this APK (not Kivy version)

Commands

$ cd ~
$ keytool -genkey -v -keystore ./keystores/<my-new-key>.keystore -alias <my-alias> -keyalg RSA -keysize 2048 -validity 10000
$ cd ~/<my-project>
$ source venv/bin/activate
$ buildozer android release
$ cd ~
$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ./keystores/<my-new-key>.keystore ./<my-project>/bin/<MyProject>-<version>-release-unsigned.apk <my-alias>
$ <key-password>
$ ~/.buildozer/android/platform/android-sdk-21/build-tools/22.0.1/zipalign -v 4 ./<my-project>/bin/<MyProject>-<version>-release-unsigned.apk ./<my-project>/bin/<MyProject>.apk


빌드도중 에러발생시
Traceback (most recent call last):
File "build.py", line 507, in 
make_package(args)
File "build.py", line 356, in make_package
subprocess.check_call([ANT, arg])
File "/usr/lib/python2.7/subprocess.py", line 540, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ant', 'debug']' returned non-zero exit status 1

Android SDK Build-tools를 revision 20으로 다운을 받고 완료되면 buildozer를 재실행한다.

  1. Run ~/.buildozer/android/platform/android-sdk-21/tools/android to launch the Android SDK Manager.
  2. Click the Deselect All link at the bottom of the window, and check the box next to "Android SDK Build-tools -- 20". screenshot from 2014-09-27 13 17 13
  3. Click the Install 1 package... button.
  4. Click Accept License and then click the Install button. screenshot from 2014-09-27 13 19 19