2017년 10월 24일 화요일

python lambda 함수의 간단 사용법





python lambda 함수의 간단 사용법
lambda 함수는 익명 함수로 알려져 있는데 기본적으로 사용 포맷은

lambda [인수1, 인수2, ...] : 인수를 이용한 표현식

의 형태이다. 즉 

lambda [parameter_list]: expression

은 아래와 동일하다. 여기서 parameter_list는 생략될수도 있다.

def <lambda>(parameter_list):
      temp = expression
      return temp

간단한 예제를 보면

>>> f = lambda x=1, y=2: x+y
>>> f()
3
>>> f(3)
5
>>> f(2)
4
>>> f(0)
2
>>> f(10)
12
>>> f(10, 20)
30
>>> f()
3

x=1, y=2는 lambda의 parameter이고 이것을 이용해서 처리할 expression은 x+y이다.
그리고 x=1, y=2는 x, y 매개인자에 아무런 값도 주어지지 않았을 때의 디폴트 값이다.
따라서 f()의 값은 3이 되는 것이다.
만일 매개인자가 하나만 주어지면(f(3)과 같이) 이때 3은 x에 대입이 되어 처리가 된다.
따라서 f(3)은 x=3, y=2가 대입되어서 5가 되고 f(2)는 4가 되는 것이고 f(10)은 12가 되는 것이다.

2017년 10월 20일 금요일

Ubuntu 12.04에서 부팅시 사용자 프로그램을 자동실행되도록 등록하기





Ubuntu 12.04에서 부팅시 사용자 프로그램을 자동실행되도록 등록하기

/etc/profile.d/ 아래에 부팅시 자동 실행시키기 위한 shell script를 만들어 두면 부팅시 해당 프로그램이 자동으로 실행이된다.

그런데 Ubuntu 12.04에서의 경우는 위의 방법으로 자동실행이 되지 않는다. 이 경우에 대한 해법이다.

~/.config/autostart/ 

여기서 ~는 리눅스 시스템에 로그인한 사용자의 홈 디렉토리를 의미한다. 
만일 kim으로 로그인했으면 ~는 /home/kim/을 의미한다.
그런데 /home/kim/.config/ 아래에 autostart라는 디렉토리가 없을수도 있다. 
이때는 autostart 디렉토리를 만들어서 자동실행을 위한 xxx.desktop 파일을 만들면 된다.

~/.config$ mkdir autostart

위 autostart 디렉토리에 임의의 xxx.desktop이라는 파일을 만들어서 자동 실행하기를 원하는 프로그램을 등록하면 부팅시 정상적으로 auto start가 된다.
이때 xxx.desktop의 내용은 다음과 같이하면된다.

[Desktop Entry]
Type=Application
Name=MyPythonTest    ===> 이 이름은 사용자가 원하는 이름으로 표시하면 된다.
Exec=/root/Downloads/PyCharmProj/MySomething.py  ===> 실행하기 원하는 프로그램 등록
X-GNOME-Autostart-enabled=true

물론 MySomething.py에 대한 필요한 코드와 권한 관련은 여기를 참조(링크)

2017년 10월 19일 목요일

Linux Ubunt에서 특정 python 프로그램을 부팅 시점에 자동으로 실행하는 방법





Linux Ubunt에서 특정 python 프로그램을 부팅 시점에 자동으로 실행하는 방법

1) /etc/profile.d 디렉토리 안에 자동실행 시키고자 하는 프로그램을 위한 쉘 스크립트를 작성한다.
예를 들어 /home/joe/xxx/FrameMove.py를 부팅시 자동 실행시키고자 하다면 /etc/profile.d안에 임의의 
쉘 스크립트를 작성만 해 두면 된다. 그러면 부팅시 /etc/profile.d안에 있는 쉘 스크립트들을 자동으로 실행한다.
   ex)  kkk.sh
        #!/bin/bash
        /home/joe/xxx/FrameMove.py

와 같이 쉘 스크립트를 작성한다.
     
2) python의 소스 코드의 첫 줄에 다음 내용을 추가한다.
   #!/usr/bin/env python

3) 실행하고자 하는 프로그램의 권한을 실행가능 형태로 권한 변경을 한다.
  ex) chmod 777 FrameMove.py

4) 저장장치에 저장되어 있는 파일들을 읽는 것과 같은 코드의 경우는 해당 파일의 절대 경로로 지정해 주어야 자동실행시 문제 없이 동작한다.
예를 들어 

img = Image.open('lenna.bmp')

와 같이 하면 터미널 창에서
python FrameMove.py와 같이 실행시는 문제 없이 실행되나(물론 lenna.bmp가 FrameMove.py와 같은 디렉토리에 있다고 할 경우)
그러나 자동실행의 방식에서는 lenna.bmp의 절대 경로를 명확히 지정해 줘야 자동실행이 가능하다. 아래와 같이 

img = Image.open('/home/joe/xxx/lenna.bmp')

5) 파일 저장을 위해 실행 경로의 권한을 쓰기 권한 부여.
만일 FrameMove.py에서 img.save("ccc.bmp")와 같이 파일을 저장하는 코드가 있다면 아마도 자동실행이 멈추면서 IOError: [Errno 13] Permission denied:라는 에러를 발생 시킬것이다.
이를 위한 해법으로 가장 단순한 방법은 FrameMove.py가 파일을 저장하는 경로의 모든 디렉토리들의 쓰기 권한을 부여하는 방법이다.
예를들어 /aaa/bbb/ccc/에 FrameMove.py가 img.save("ccc.bmp")의 동작을 한다면 aaa, bbb, ccc 디렉토리의 쓰기권한을 부여해주어야 한다.
chmod 777 aaa ...
와 같이하면 자동 실행에서의 발생할수 있는 권한 문제를 해결할수 있다.


2017년 10월 12일 목요일

Debian 계열(Ubuntu)에서 설치 패키지 직접 다운로드 및 설치하기





Linux에서 필요한 작업을 위해 필요한 패키지들을 설치하는 일이 윈도우와는 달리 상당히 번거롭고 혹은 까다롭고 심지어는 불가능할수도 있다.
가장 대표적으로는 apt-get install some_package_name
으로 설치가 되는 경우는 Linux 버전이 최신 버전이거나 사용하는 cpu가 통상적으로 많이 사용되는 경우들이다. 이런 경우는 repository에 해당 패키지가 있기 때문에 쉽게 설치가 된다.
동일한 Ubuntu에서도 CPU architecture가 다를 경우는 역시 설치에 문제가 많이 발생한다.

우선 사용중인 Linux가 어떤 종류인지 확인해 보자. 명령어는
# grep . /etc/*-release

다음과 같이 리눅스 종류와 버전 정보가 나타난다.
아래의 경우는 Ubuntu 16.04인 경우이다.

/etc/lsb-release:DISTRIB_ID=Ubuntu
/etc/lsb-release:DISTRIB_RELEASE=16.04
/etc/lsb-release:DISTRIB_CODENAME=xenial
/etc/lsb-release:DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
/etc/os-release:NAME="Ubuntu"
/etc/os-release:VERSION="16.04.3 LTS (Xenial Xerus)"
/etc/os-release:ID=ubuntu
/etc/os-release:ID_LIKE=debian
/etc/os-release:PRETTY_NAME="Ubuntu 16.04.3 LTS"
/etc/os-release:VERSION_ID="16.04"
/etc/os-release:HOME_URL="http://www.ubuntu.com/"
/etc/os-release:SUPPORT_URL="http://help.ubuntu.com/"
/etc/os-release:BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
/etc/os-release:VERSION_CODENAME=xenial
/etc/os-release:UBUNTU_CODENAME=xenial

다음은 리눅스 커널이 몇 bit인지를 확인해 보자

# getconf LONG_BIT

이 경우 32bit인경우 32, 64bit인 경우는 64의 값을 출력해 준다.

다음은 사용중인 cpu architecture가 무엇인지를 알아보자

# dpkg --print-architecture

여기서 amd64, i386, armhf 등의 해당 정보가 표시된다.
이러한 정보들을 가지고 패키지가 정상적으로 설치되지 않을 경우 활용할수 있는 정보들이다.
repository를 추가해서 설치하거나, 소스를 다운로드 받아서 새롭게 컴파일하는 등의 방법이 있으나 본 포스트에서는 Ubuntu(Debian 계열)의 경우 해당 버전, architecture등에 맞는 설치 패키지들이 잘 준비가 되어 있고 이것을 그냥 다운로드 받아서 dpkg라는 패키지 설치 명령어로 설치하는 방법에 대해서 정리하고자 한다.

참고로 repository를 추가하는 방법은

vi  /etc/apt/sources.list 파일을 열어서 해당 repository를 추가 및 저장한 후

# apt-get update를 한 후 apt-get install로 해당 패키지 설치를 시도해 보면 된다.

아래 사이트는 Ubuntu와 같은 Debian 계열의 각종 리눅스 종류와 버전들, 각종의 programming language들에 필요한 대한 매우 다양한 종류의 설치 패키지(.deb)가 잘 마련되어 있다. 


예를 들어 Python에서 사용할 Kivy 패키지를 찾고자 한다면 웹브라우저 상의 Ctrl-F로 Python을 찾는다. 찾아진 Python 항목을 클릭해서 들어가면 다음과 같은 웹 페이지가 열린다.


이 페이지에서 역시 Ctrl-F로 Kivy 항목을 찾는다. 그러면 다음과 같은 항목들이 있을 것이다.

python-kivy (1.9.1-1+b1 [alpha, amd64, arm64, armel, armhf, hppa, hurd-i386, i386, kfreebsd-amd64, kfreebsd-i386, m68k, mips, mips64el, mipsel, powerpc, powerpcspe, ppc64, ppc64el, s390x, sparc64, x32], 1.9.1-1 [sh4])
Kivy - Multimedia / Multitouch framework in Python (Python 2)

python-kivy-examples (1.9.1-1)
Kivy - Multimedia / Multitouch framework in Python (examples)

여기서 python-kivy를 설치하고자 할경우 위의 첫 번째 항목을 클릭해서 들어가면 해당 패키지에 대한 설명과 관련 의존성 패키지들(dependency packages)이 모두 나와 있고 아랫쪽에 내려가면 python-kivy에 대한 Architecture별로 다운로드 받을수 있도록 목록이 나와있다.
해당 architecture를 선택해서 들어가면 다운로드 받을수 있는 ftp들 목록이 나온다. 원하는 목록에 대해 마우스 우측 클릭해서 해당 경로의 url 주소를 가지고 Linux에서 wget을 이용해서 다운로드 받은후(xxx.deb) dpkg로 설치하면 된다.

wget http://ftp.kr.debian.org/debian/pool/main/k/kivy/python-kivy_1.9.1-1+b1_armhf.deb 

혹은 리눅스의 웹브라우저로 위의 사이트에 들어가서 직접 다운로드 해도 된다.
설치는 다음과 같이

dpkg -i python-kivy_1.9.1-1+b1_armhf.deb 

리눅스의 경우 패키지 설치는 매우 다양한 변수들에 영향을 받는다. 따라서 상황따라 대처해야 하는수 밖에 없다.

2017년 10월 8일 일요일

Kv language를 이용한 Kivy 프로그래밍 하기 - Builder 클래스 이용하기





이번에는 Builder 클래스 중 load_string() 메소드를 이용하는 방법에 대해 소개한다. load_file()은 어렵지 않은 개념이므로 생략

from kivy.app import App
from kivy.lang import Builder

kvImg = """
FloatLayout:
    Image:
        source:'ccc.bmp'
        size_hint: 0.7, 0.7  # None, None
        post_hint: {'center_x': 1, 'center_y': 1}
        canvas.before:
            PushMatrix
            Rotate:
                angle: 45
                origin: self.center
        canvas.after:
            PopMatrix
"""

class RotationApp(App):
    def build(self):
        print 'kvImg : ', kvImg
        # return Builder.load_string(kv)
        return Builder.load_string(kvImg)

RotationApp().run()

이렇게 하면 kv language를 이용해서 45도 회전한 이미지를 화면에 보여줄수 있다.

Kv language를 이용한 Kivy 프로그래밍 하기 - 이름으로 지정하기





Kivy를 이용해서 python에서 GUI 프로그래밍을 할 때 Kivy만이 가진 특성 중 하나인 Kv language를 사용하는 방법에 대한 간단한 개념이다.
kv code를 python 코드에 포함(load)시키는 방법에는 2가지 방법이 있다.

1. by name convention(이름으로 지정하는 방법)
python의 클래스 이름과 동일한 kv 파일명을 가진 kv 파일을 만들면 자동으로 이 파일을 load한다.

2. Builder 클래스를 이용하여 직접 python 코드에 load하는 방법
  -. Builder.load_file('some/path/somefile.kv')
  -. Builder.load_string(my_kv_string) 
     이 경우는 python 코드 안에서 string 형태로 kv 코드를 만들고 이를 Build.load_string()을 이용해서 사용하는 방석이다.

아래의 코드는 by name convention 방식으로 kv 코드를 python 코드에 load하는 방법이다.

  • exkvtest.kv의 내용이다
<Label>
    text: 'Hello'+' World'
    font_size: 50


  • exkvtest.py의 내용이다.
#-*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.label import Label

'''
kv의 원리
-. kv 파일명과 python 파일명이 같아야 함. 단 모두 소문자라야 함. ExKvTest.kv, ExKvTest.py식이면 안됨.
-. exkvtest.kv, exkvtest.py식이어야 한다
-. python 소스 코드의 클래스 이름도 kv 파일과 동일해야 한다. 단 소스 코드에서의 class 이름은 소문자로만 하지 
-. 않아도 된다. class ExKvTest(App)과 같이 해도 된다. 또한 소스 코드상에서의 class이름 끝에 App이라는 문자는 상관없다.

There are two ways to load Kv code into your application:
By name convention:
   Kivy looks for a Kv file with the same name as your App class in lowercase, minus “App” if it ends with ‘App’ e.g:
      MyApp -> my.kv
'''

# 안됨
# class MyKvTest(App):
#     def build(self):
#         # return Label(text='Hi~')
#         return Label()

# 잘 됨
class ExKvTestApp(App):
    def build(self):
        # return Label(text='Hi~')
        return Label()


if __name__ == '__main__':
    # MyKvTest().run()  # 안됨
    ExKvTestApp().run()  # 잘됨

2017년 10월 2일 월요일

Ubuntu상에서의 Python GUI용 Kivy 사용시 ImportError: No module named 문제 출처: http://developer-joe.tistory.com/ [코드 조각-Android, Java, C#, C, C++, JavaScript, PHP, HTML, CSS, Delphi]





python을 이용해서 Linux 상에서 구동되는 GUI 프로그램을 개발할 일이 있어서 QT, Tkinter, kivy들을 테스트 하게되었다.
PyCharm을 이용해서 kivy 관련 코드들이 정상적으로 잘 실행이 되었다.
근데 terminal 창에서 kivy관련 코드를 실행하면(python test.py) 

ImportError: No module named 'kivy'

와 같은 에러를 계속 뿜어 낸다.
분명히 kiviy 공식 사이트가 지정해 주는대로 kivy를 정상적으로 잘 설치했고 따라서 PyCharm에서 잘 실행이 되었다.
그런데 유독 터미널 창에서만 실행이 되지를 않았다.
결국 문제는 path상에서 인식으로 하지 못한 문제였다. 원인은 anaconda를 설치했다가 삭제를 했는데 path상에는 여전히 그 놈이 살아있어서 path를 읽어가는 중에 문제를 일으킨것 같다.

root@joe-VirtualBox:/usr/lib/python2.7/dist-packages/kivy/uix# echo $PATH
/root/anaconda2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

위와 같이 이미 삭제된 anaconda가 살이있어서의 문제였다.
/root/.bashrc에 있는 

export PATH="/root/anaconda2/bin:$PATH"

이 놈을 주석으로 묶어 버렸더니 터니널 창에서도 정상적으로 kivy가 잘 동작했다.
리눅스는 아무튼 복잡한 동물이라서... 쩝

Ubuntu Linux에 packages들을 offline에서 설치하기





Ubuntu Linux에 packages들을 offline에서 설치하기

apt-get install로 패키지들을 설치할 경우 해당 패키지는 
일단 /var/cache/apt/archives/에 다운로드 되서 설치가 된다.
이때 다운로드 될 때 특정 패키지와 의존성(dependency)있는 패키지들까지 같이 다운로드 되어서 설치가된다.
따라서 우리가 인터넷이 되지 않는 장비나 shell script를 이용해서 일괄적으로 여러 장비들에 필요한 패키지들을 설치해야 할 경우 등에 이 방법을 사용하면 된다.

우선 VirtualBox와 같은 가상 머신에 실제 장비와 같은 환경의 Linux 버전과 가능하다면 같은 architecture, 같은 커널의 bit와 동일한 환경을 만든다.
이 상태에서 apt-get install을 이용하여 필요한 모든 패키지들을 설치를 한다.

그 후 /var/cache/apt/archives에 있는 패키지들을 tar -cvf xxx.tar /var/cache/apt/archives/와 같이 압출을 한다.
이렇게 압축된 파일을 offline상의 디바이스에 복사해서 옮긴다(당연히 압축은 푼다).

압축을 푼 디렉토리에 가서 다음의 명령으로 모든 패키지들을 일괄적으로 설치를 한다.

# dpkg --force-all -i *.deb

위 명령은 의존성을 무시하고 강제로 특정 패키지를 설치하는 형태인데 이렇게 해도 괜찮은 이유가 압축을 푼 모든 *.deb 패키지들이 모든 의존성 패키지들을 다 담고 있는 것이기 때문에 다 설치가 되면 모든 의존성까지 다 해결된 상태로 설치가 될것이기 때문이다.
여러 임베디드 장비에 설치해야 할 경우등에 응용하면 될 것이다.

Windows 10에서 창 배경색(메모장 배경 색, 응용 프로그램 배경 색) 변경하기





Windows 10의 메모장, 아래아 한글, 워드 패드... 응용 프로그램들의 배경 색이 강렬한 흰색으로 고정되어 이것을 변경하기가 여간 힘든게 아니다. 이전 버전의 Windows들에서 쉽게 변경되던 것들이 버전이 올라가면서 점점 변경하기 어렵게 되어 버렸다.

레지스트리의 값을 변경하는 방법도 있으나(자세한 내용은 여기를 참조) '최대 절전 모드' 등으로 들어갔다가 나오면 레지스트리 변경된 값이 적용이 안되는 문제가 있어 오늘은 일종의 꼼수이지만 이 문제를 보다 간편하게 이용할수 있는 방법을 정리해 보고자 한다.

핵심은 테마(Theme)의 값을 변경함으로 통해서 소기의 목적을 달성코자 한다. 
아래 경로로 가보면 다음과 같은 테마 파일들이 있다.

C:\Windows\Resources\Themes

aero             [DIR] 2017-08-18 00:39:08 ____ 
theme2.theme     2,306 2017-03-19 05:59:08 a___ 
theme1.theme     2,250 2017-03-19 05:59:08 a___ 
aero.theme       1,898 2017-03-19 05:58:27 a___ 
Samsung.theme    1,846 2015-09-30 17:01:58 a___ 

윈도우의 배경색, 바탕화면 배경 이미지, 마우스 관련 등등에 대한 정보를 담고 있고 그런 내용을 결정하는 파일인 테마(Theme)파일들이다.

우리가 정말 간절히 원하는 것은 메모장이나 아래아 한글, 워드패드... 등등의 강렬한 흰색 배경색을 우리가 원하는 색상으로 변경하고자 하는 것이다.
이 문제를 regedit을 이용해서 레지스트리 값을 변경하는 방법으로는 최초 부팅시에는 해당 배경 색이 적용이 되나 '최대 절전 모드'에 들어갔다가 나오면 배경 색상이 원상복구되어 강렬한 흰색이 눈을 자극하는 불쾌하기 짝이 없는 상황에 다시 봉착하게 된다.

이 문제를 해결하는 그래도 대안이 테마의 정보를 담고 있는 파일에 우리가 원하는 색상 정보를 추가하는 것이다.
아래는 aero.theme을 메모장으로 열었을 때의 정보이다.

; Copyright ?Microsoft Corp.

[Theme]
; Windows - IDS_THEME_DISPLAYNAME_AERO
DisplayName=@%SystemRoot%\System32\themeui.dll,-2013
SetLogonBackground=0

; Computer - SHIDI_SERVER
[CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon]
DefaultValue=%SystemRoot%\System32\imageres.dll,-109

; UsersFiles - SHIDI_USERFILES
[CLSID\{59031A47-3F72-44A7-89C5-5595FE6B30EE}\DefaultIcon]
DefaultValue=%SystemRoot%\System32\imageres.dll,-123

; Network - SHIDI_MYNETWORK
[CLSID\{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}\DefaultIcon]
DefaultValue=%SystemRoot%\System32\imageres.dll,-25

; Recycle Bin - SHIDI_RECYCLERFULL SHIDI_RECYCLER
[CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\DefaultIcon]
Full=%SystemRoot%\System32\imageres.dll,-54
Empty=%SystemRoot%\System32\imageres.dll,-55

[Control Panel\Cursors]
AppStarting=%SystemRoot%\cursors\aero_working.ani
Arrow=%SystemRoot%\cursors\aero_arrow.cur
Crosshair=
Hand=%SystemRoot%\cursors\aero_link.cur
Help=%SystemRoot%\cursors\aero_helpsel.cur
IBeam=
No=%SystemRoot%\cursors\aero_unavail.cur
NWPen=%SystemRoot%\cursors\aero_pen.cur
SizeAll=%SystemRoot%\cursors\aero_move.cur
SizeNESW=%SystemRoot%\cursors\aero_nesw.cur
SizeNS=%SystemRoot%\cursors\aero_ns.cur
SizeNWSE=%SystemRoot%\cursors\aero_nwse.cur
SizeWE=%SystemRoot%\cursors\aero_ew.cur
UpArrow=%SystemRoot%\cursors\aero_up.cur
Wait=%SystemRoot%\cursors\aero_busy.ani
DefaultValue=Windows Aero
DefaultValue.MUI=@main.cpl,-1020

[Control Panel\Desktop]
Wallpaper=%SystemRoot%\web\wallpaper\Windows\img0.jpg
TileWallpaper=0
WallpaperStyle=10
Pattern=

[VisualStyles]
Path=%ResourceDir%\Themes\Aero\Aero.msstyles
ColorStyle=NormalColor
Size=NormalSize
AutoColorization=0
ColorizationColor=0XC40078D7

[boot]
SCRNSAVE.EXE=

[MasterThemeSelector]
MTSM=RJSPBS

[Sounds]
; IDS_SCHEME_DEFAULT
SchemeName=@%SystemRoot%\System32\mmres.dll,-800

이 테마 파일을 그대로 복사해서 배경색으로 보다 편리하게 변경해서 사용하고자 한다.
변경 절차이다.

1. 도스창을 관리자 권한으로 연다.

2. copy aero.theme joe.theme (joe.theme는 변경하기 원하는 테마 파일의 이름으로 임의로 지정하면 된다)

3. notepad(메모장)을 관리자 권한으로 열어 joe.theme를 연다.

4. 아래 내용을 [Control Panel\Desktop] 항목 위에 추가한 후 저장한다. 209 224 224로 되어 있는 색상 값은 원하는 색상 값으로 작성하면 된다.

[Control Panel\Colors]
Window=209 224 224

색상 변경 값은 Red(209), Green(224), Blue(224)로 설정된 색상이다. 
색상 변경 색은 다음 사이트에서 본인이 원하는 색상 값을 확인할수 있다.


5. 파일 탐색기를 열어서 joe.theme에 대한 바로가기를 만든다. 만드는 방법은 joe.theme에 대해 마우스 우측 클릭한 후 팝업메뉴에서 바로가기를 만들면 바탕화면에 바로가기가 만들어진다.

6. 컴퓨터를 부팅 후 joe.theme를 클릭하면 테마관련 창이 뜨는데 그냥 닫으면 그 때 이후부터는 변경된 색상이 모든 프로그램의 배경 색상으로 나타나서 우리의 눈을 편안하게 해 준다.

7. 나쁜 Microsoft 같으니라고~

8. joe.theme가 반드시 C:\Windows\Resources\Themes 이 경로에 위치해야 할 필요는 없다. 편한 곳에 복사해 두었다가 필요할 때 실행하면 된다. 왜냐하면 C:\Windows\Resources\Themes 이 경로에서는 이 파일을 편집하는 것이 관리자 권한이 아니면 안되기 때문에 다른 폴더에 복사해 둔 경우는 색상 변경시 메모장으로 열어서 쉽게 변경된 내용을 저장할수 있기 때문에 다른 경로에 복사해 두면 오히려 더 편리하다.