pipenv 소개

Pipenv 뭐하는 녀석인가?

  • python.org 에서 공식적으로 추천하는 패키지 관리툴
  • 세계에서 제일가는 패키징툴을 만드는게 목표라고 한다…
  • virtualenv 환경을 자동으로 만들어 준다.
  • Pipfile 에 패키지를 더하거나 빼거나 하면 됨.
  • Pipfile이라는 녀석이 Pipfile.lock 이라는 겁나 중요한 파일을 생성하는데, 결정론적 빌드(deterministic builds)에 쓰인다.
  • 이거 만든사람은… requests 만든사람이다. requests를 만들었을 때처럼 인터페이스가 깔끔하다.
  • 지 블로그에는 주말에 만들었다고 올려놨다… https://www.kennethreitz.org/essays/announcing-pipenv
  • 주말에 만들었다고는 하지만, 케네스의 깃헙을 보면 비슷한 시도들을 많이 한것으로 보인다.
  • 즉, 능력자의 삽질의 결과물인 것이다.

Pipenv가 해결하려고 하는 문제들

  • pip 와 virtualenv 를 분리된 상태로 사용하는 것이 아니라, pipenv 하나만 사용하기
  • requirement.txt 파일의 관리를 별도의 코드가 아닌 Pipfile, Pipfile.lock 으로 할 수 있도록 해주는 것
  • 해쉬의 자동생성(보안관련)
  • pipenv graph 명령어로 의존성 그래프를 직관적으로 볼 수 있음
  • .env 파일들을 사용한 스트림라인 개발 워크플로우

기능들

  • 딱 필요한 것만 정의 하면서도, 레알 결정론적 빌드가 가능하다.
    • 결정론적 빌드라는게 뭐냐면 그냥 파일에 정해진대로 빌드를 할 수 있다는 말이고,
      빌드가 상황과 환경에 좌지우지 되지 않는 다는 것을 말한다.
  • 락이 걸린 의존성에 대한 해쉬 파일들을 만들어준다. (Pipenv.lock 파일)
  • pyenv가 설치되어 있으면, 파이썬도 자동으로 설치해줌
  • Pipfile 을 사용해서 자동으로 프로젝트 홈을 찾아줌
  • Pipfile이 없으면 자동으로 만들어줌
  • 자동으로 virtualenv 환경을 만들어줌
  • Pipfile 에서 추가/삭제하면 해당 패키지도 추가/삭제 됨. (오 좀 짱인듯)
  • .env 파일이 있으면 자동으로 인식 (환경변수를 자동으로 인식할 수 있음)
  • 주된 커맨드는 install, uninstall, lock 이고, 요넘들은 Pipfile.lock 이라는 파일을 만들어냄.

기본 컨셉

  • virtualenv 환경(이 없으면) 자동 생성
  • install 커맨드에 파라메터를 안넣으면 정의 되어 있는 의존성 몽땅 설치
  • pipenv --three 실행하면 python3 환경을 뚝딱 만들어줌
  • pipenv --two 실행하면 python2 환경을 만들어줌
  • 이러나 저러나 virtualenv 는 기본이자 기본이다.
  • 한마디로 줄이면 자동생성을 수동으로(커맨드는 날려야되니) 편리하게 해준다 정도

다른 명령어들

  • shell : virtualenv 환경 활성화
  • run : virtualenv 의 run 커맨드랑 동일
  • check : 현재의 환경이 PEP508 의 스펙 내용을 만족하는지 확인
  • graph : 의존성 트리를 보여줌

Shell Completion (뭐라해야될지 모르겠지만, 쉘에 넣어두면 pipenv가 활성화됨)

  • eval “$(pipenv –completion)”
  • fish shell 이 젤좋은  쉘이라고 쓰라고 약을 팔고 있으나 안쓸꺼임 ㅎㅎ
#### 프로젝트 위치 찾기
$ pipenv --where
#### virtualenv 위치 찾기
$ pipenv --venv
#### python 인터프리터 위치 찾기
$ pipenv --py

사용법

$ pipenv
Usage: pipenv [OPTIONS] COMMAND [ARGS]...
Options:
  --update         Update Pipenv & pip to latest.
  --where          Output project home information.
  --venv           Output virtualenv information.
  --py             Output Python interpreter information.
  --envs           Output Environment Variable options.
  --rm             Remove the virtualenv.
  --bare           Minimal output.
  --completion     Output completion (to be eval'd).
  --man            Display manpage.
  --three / --two  Use Python 3/2 when creating virtualenv.
  --python TEXT    Specify which version of Python virtualenv should use.
  --site-packages  Enable site-packages for the virtualenv.
  --jumbotron      An easter egg, effectively.
  --version        Show the version and exit.
  -h, --help       Show this message and exit.
Usage Examples:
   Create a new project using Python 3.6, specifically:
   $ pipenv --python 3.6
   Install all dependencies for a project (including dev):
   $ pipenv install --dev
   Create a lockfile containing pre-releases:
   $ pipenv lock --pre
   Show a graph of your installed dependencies:
   $ pipenv graph
   Check your installed dependencies for security vulnerabilities:
   $ pipenv check
   Install a local setup.py into your virtual environment/Pipfile:
   $ pipenv install -e .
Commands:
  check      Checks for security vulnerabilities and...
  graph      Displays currently–installed dependency graph...
  install    Installs provided packages and adds them to...
  lock       Generates Pipfile.lock.
  open       View a given module in your editor.
  run        Spawns a command installed into the...
  shell      Spawns a shell within the virtualenv.
  uninstall  Un-installs a provided package and removes it...
  update     Uninstalls all packages, and re-installs...

설치하기

$ pip install pipenv

의존성 패키지 설치

### 1개 설치
$ pipenv install pytest
$ pipenv install

개발환경일때의 의존성 패키지 설치

### 1개 설치
$ pipenv install pytest --dev
### 전부 설치
$ pipenv install --dev

파이썬 shell 사용하기

$ pipenv shell

프로젝트에 적용 해보기

django로 되어 있는  프로젝트에 적용해 보자

### 프로젝트 루트 디렉토리로 이동
$cd exid
### 아무것도 없지만, 몽땅 설치를 실행한다!
$ ppipenv install
Creating a virtualenv for this project…
⠋Using base prefix '/pyenv/versions/3.4.3'
New python executable in /
Installing setuptools, pip, wheel...done.
Virtualenv location: /
Requirements.txt found, instead of Pipfile! Converting…
Warning: Your Pipfile now contains pinned versions, if your requirements.txt did.
We recommend updating your Pipfile to specify the "*" version, instead.
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (489182)!
Installing dependencies from Pipfile.lock (489182)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 31/31 00:00:25
To activate this project's virtualenv, run the following:
 $ pipenv shell
Spawning environment shell (/usr/local/bin/zsh). Use 'exit' to leave.
source /activate
# Load pyenv-virtualenv automatically by adding
# the following to ~/.zshrc:
eval "$(pyenv virtualenv-init -)"
  • pipenv 가 실행된 다음의 로그를 읽어보자
  • virtualenv 환경이 없으니 pipenv가 pyenv의 파이썬 버전을 읽어서 virtualenv를 하나 만들어준다. virtualenv 이름이 마음에 안들긴 하는데, 딱히 잘 안쓰니 상관없나 싶기도 함
  • 놀랍게도 requirements.txt 파일이 있는 것을 찾아냈다.
  • Pipfile.lock 도 없어서 만들어주고, requirements.txt에 설정된 패키지들을 몽땅 설치하고, Pipfile.lock 도 업데이트를 한다.

pipenv 로 만든 virtualenv 환경 활성화 하기

#### pipenv shell 을 실행하면 virtualenv 환경으로 만들어줌
$ pipenv shell
➜  exid git:() ✗ source /~/exid-NTYXrrm5/bin/activate
(exid-NTYXrrm5) ➜  exid git: ✗
  • 역시나 랜덤하게 만들어지는 virtualenv 이름은 마음에 안든다.

pipenv run

virtualenv를 활성화 하지 않고 해당 환경에서 파이썬 파일을 실행하는 방법은 pipenv run 커맨드를 이용하는 것이다.

$ pipenv run python my_project.py

자주 사용하게될 녀석이니 앨리어스로 등록해두자. vim 사용자라면, .vimrc 에 추가하면 된다.

### 별칭은 알아서 잘 만들자
alias pipython="pipenv run python"
alias prp="pipenv run python"

Pipfile과 Pipfile.lock

Pipfile

  • 위에서 pipenv install 명령어 한방으로 생성한 파일이다.
  • dev 는 아직 없으나 나중에 필요하면 채워놓자.
[[source]]
name = "pypi"
verify_ssl = true
[packages]
amqp = "==2.1.4"
billiard = "==3.5.0.2"
celery = "==4.0.2"
"contextlib2" = "==0.5.4"
Django = "==1.8.5"
django-braces = "==1.9.0"
django-crispy-forms = "==1.6.1"
django-extensions = "==1.7.4"
django-floppyforms = "==1.7.0"
djangorestframework = "==3.3.1"
elasticsearch = "==2.4.0"
kombu = "==4.0.2"
mysqlclient = "==1.3.7"
olefile = "==0.44"
Pillow = "==4.0.0"
pycrypto = "==2.6.1"
pytz = "==2016.10"
raven = "==6.2.1"
redis = "==2.10.5"
redis-py-cluster = "==1.1.0"
requests = "==2.9.1"
serpy = "==0.1.0"
simplejson = "==3.10.0"
"urllib3" = "==1.19.1"
uWSGI = "==2.0.15"
vine = "==1.1.3"
xlwt = "==1.2.0"
mongoengine = "==0.13.0"
django-widget-tweaks = "==1.4.1"
[dev-packages]

Pipfile.lock

{
    "_meta": {
        "hash": {
            "sha256": "e0bb552e2ab575fa5141985b686ac5e49da21bdda3444cfd1273a5927f489182"
        },
        "host-environment-markers": {
            "implementation_name": "cpython",
            "implementation_version": "3.4.3",
            "os_name": "posix",
            "platform_machine": "x86_64",
            "platform_python_implementation": "CPython",
            "platform_release": "17.3.0",
            "platform_system": "Darwin",
            "platform_version": "Darwin Kernel Version 17.3.0: Thu Nov  9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64",
            "python_full_version": "3.4.3",
            "python_version": "3.4",
            "sys_platform": "darwin"
        },
        "pipfile-spec": 6,
        "requires": {},
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.python.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "amqp": {
            "hashes": [
                "sha256:5e0871a93433f941e444c2b859da095f05034d2ac1b7c084529cfd0b6f8eef18",
                "sha256:1378cc14afeb6c2850404f322d03dec0082d11d04bdcb0360e1b10d4e6e77ef9"
            ],
            "version": "==2.1.4"
        },
        "billiard": {
            "hashes": [
                "sha256:82478ebdd3cd4d357613cb4735eb828014364c5e02d3bba96ea6c1565a2c0172",
                "sha256:a93c90d59fca62ad63f92b3d2bf1d752c154dde90a3100dba4c8e439386e534c",
                "sha256:d8df4b276b11b3e2fe25652e411487bda6e5bac4f8fd236a278a2bfe300f7c43",
                "sha256:e740e352bbf7b6c8cc92a2596cc2da2bfb4ab1009aeb68bf844456af4e924278",
                "sha256:52c2e01c95c6edae9ca1f48d83503e6ceeafbf28c19929a1e917fe951a83adb1",
                "sha256:03f669755f1d6b7dbe528fe615a3164b0d8efca095382c514dd7026dfb79a9c6",
                "sha256:3eb01a8fe44116aa6d63d2010515ef1526e40caee5f766f75b2d28393332dcaa"
            ],
            "version": "==3.5.0.2"
        },
          ... 중략
    },
    "develop": {}
}
  • Pipfile.lock 은 의존성 패키지의 검증을 담당한다.
  • 의존성이 있는 패키지가 의존하고 있는 패키지들도 함께 검사를 해주게 되므로 Pipfile.lock 을 잘 사용해서 안심하고 쓸 수 있게 되는 것이다.

dev 에 패키지를 추가해보자

$ pipenv install mock --dev
Installing mock…
Collecting mock
  Downloading mock-2.0.0-py2.py3-none-any.whl (56kB)
Collecting pbr>=0.11 (from mock)
  Downloading pbr-3.1.1-py2.py3-none-any.whl (99kB)
Requirement already satisfied: six>=1.9 in //lib/python3.4/site-packages (from mock)
Installing collected packages: pbr, mock
Successfully installed mock-2.0.0 pbr-3.1.1
Adding mock to Pipfile's [dev-packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (bd3f8c)!
  • Pipfile 에 추가하고
  • 각 환경에서의 의존성이 걸리는 부분을 확인 한다음
  • Pipfile.lock 을 업데이트한다.

Pipfile [dev-packages] 부분

[dev-packages]
mock = "*"

Pipfile.lock  “develop” 부분

"develop": {
    "mock": {
        "hashes": [
            "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1",
            "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"
        ],
        "version": "==2.0.0"
    },
    "pbr": {
        "hashes": [
            "sha256:60c25b7dfd054ef9bb0ae327af949dd4676aa09ac3a9471cdc871d8a9213f9ac",
            "sha256:05f61c71aaefc02d8e37c0a3eeb9815ff526ea28b3b76324769e6158d7f95be1"
        ],
        "version": "==3.1.1"
    },
    "six": {
        "hashes": [
            "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
            "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
        ],
        "version": "==1.11.0"
    }
}

개발환경과 운영환경에서는 어떻게 적용할까?

개발환경

–dev 를 붙이면 [packages] 와 [dev-packages] 둘다 설치하므로 아래의 명령어를 그냥 날리면 된다.

pipenv install --dev

샌박, 베타, 실서버

운영환경에서는 [packages] 에 있는 것만 설치하면 되니 –dev 를 빼고 실행하면 되겠다.

$ pipenv install

참고

깃헙 : https://github.com/pypa/pipenv

매뉴얼 : https://media.readthedocs.org/pdf/pipenv/latest/pipenv.pdf

케네스 아저씨 블로그 : https://www.kennethreitz.org/essays/announcing-pipenv

Django tutorial1

[markdown]
#django 튜토리얼1

###쟝고의 기능들
– ORMapper
– Automatic admin interface
– Elegant URL design
– Template system
– cache system
– Internationalization

###쟝고 설치됐는지 확인하기

`python -c “import django; print(django.get_version())”`

###project 만들기

`django-admin.py startproject mysite`

위에꺼 실행하면 아래와 같은 디렉토리 & 파일이 생성됨

“`shell
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
“`

– manage.py : 커맨드라인 유틸리티. 자세한 것은 다음링크에서 확인가능 [django-admin.py and manage.py](https://docs.djangoproject.com/en/1.6/ref/django-admin/)
– mysite 디렉토리 안의 mysite : 디렉토리가 실제 만들게될 프로젝트의 디렉토리
– mysite/settings.py : 쟝고프로젝트 설정파일. 자세한 것은 다음 링크에서 [Django settings](https://docs.djangoproject.com/en/1.6/topics/settings/)
– mysite/urls.py : 쟝고프로젝트의 URL정의 파일. 자세한 것은 다음 링크에서 확인 [URL dispatcher](https://docs.djangoproject.com/en/1.6/topics/http/urls/)
– mysite/wsgi.py : WSGI과 호환되는 웹서버의 시작점. 자세한 것은 다음 링크로 [How to deploy with WSGI](https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/)

##### 서버기동
`python manage.py runserver`

##### 데이터베이스 세팅
디폴트는 sqlite3이고, 다른 데이터베이스를 사용하려면 mysite/settings.py의 `DATABASES` 부분을 수정해주어야한다. (나는 mongodb쓸껀데…) 데이터베이스 세팅에 관한 내용은 다음 링크에 있음 [setting-DATABASE-ENGINE](https://docs.djangoproject.com/en/1.6/ref/settings/#std:setting-DATABASE-ENGINE)

##### 타임존 설정(TIME_ZONE)
나는 대한민국 사람이니 mysite/settings.py 의 TIME_ZONE을 ‘Asia/Seoul’로 변경함. 기본은 ‘America/Chicago’
언어는 귀찮아서 냅둠.

##### 설치된 앱들

settings.py에 보면 INSTALLED_APPS라는 파라메터가 있는데, 현재의 쟝고 인스턴스에서 활성화 된 쟝고 어플리케이션의 이름들을 적어놓은 곳이다. APP은 여러 프로젝트에서 사용가능하고 패키징하고 배포가 가능해서 다른 프로젝트에서도 사용될 수 있다.

디폴트로 포함되어 있는 앱들

– django.contrib.admin – 관리자페이지
– django.contrib.auth – 인증시스템
– django.contrib.contenttypes – 컨텐트타입 프레임웤
– django.contrib.sessions – 세션 프레임웤
– django.contrib.messages – 메세징 프레임웤
– django.contrib.staticfiles – 정적파일을 위한 프레임웤

##### syncdb
`$ python manage.py syncdb`

syncdb 커맨드는 INSTALLED_APPS의 설정을 보고 필요한 데이터베이스 테이블을 생성한다.
처음 실행할때 admin유저를 만들 수 있다.

##### app 만들기
`python manage.py startapp polls`

mysite의 탑레벨 모듈로 polls모듈을 만들자.

디렉토리는 아래와 같이 생겼다.

“`shell
polls/
__init__.py
admin.py
models.py
tests.py
views.py
“`

##### 모델만들기

polls/models.py 를 아래와 같이 고친다.

“`python
from django.db import models

class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField(‘date published’)

class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
“`

하나의 클래스는 테이블과 매핑되고 하나의 변수는 하나의 필드와 매핑이 된다. 그리고 Choice클래스에 외래키를 지정했는데 django는 관계형디비의 모든 관계(다대다 일대다 일대일)를 지원한다.

##### 모델 활성화하기

mysite/settings.py의 파일을 다시 열어서 아래와 같이 수정한다.

“`python
INSTALLED_APPS = (
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘polls’,
)
“`

이제 쟝고가 polls앱이 포함된 것을 알게됐다. 다음으로 아래의 명령을 실행해보자.

`$ python manage.py sql polls`

그러면 아래와 같은 SQL문이 콘솔에 찍힌다.

“`sql
BEGIN;
CREATE TABLE “polls_poll” (
“id” integer NOT NULL PRIMARY KEY,
“question” varchar(200) NOT NULL,
“pub_data” datetime NOT NULL
)
;
CREATE TABLE “polls_choice” (
“id” integer NOT NULL PRIMARY KEY,
“poll_id” integer NOT NULL REFERENCES “polls_poll” (“id”),
“choice_text” varchar(200) NOT NULL,
“votes” integer NOT NULL
)
;
“`

– 콘솔에 찍힌 SQL은 우리가 지정한 혹은 기본인 sqlite3 데이터 베이스에 사용되는 SQL문임을 알 수 있다.
– 테이블명은 자동적으로 app(polls)과 소문자 모델클래스명을 결합하여 만들어진다.
– 프라이머리키(IDs)는 자동으로 추가된다. (오버라이딩 가능)
– 관례로, 쟝고는 ‘_id’를 외래키명에 붙인다.
– 외래키 관계는 REFFERNCE문으로 정확히 만들어졌다.
– `sql`명령어는 실제로 SQL을 실행하지는 않고 단순히 출력만 해준다.

관심있으면 아래 명령어도 테스트해보길

– python manage.py validate – 모델이 유효한지 체크해줌
– python manage.py sqlcustom polls – 테이블 변경이나 제약수정을 위한 명령어를 출력
– python manage.py sqlclear polls – 테이블 삭제를 위한 쿼리를 출력
– python manage.py sqlindexes polls – 인덱스 생성문을 출력
– python manage.py sqlall polls – 해당앱에 사용된 모든 쿼리를 합쳐서 출력

`syncdb`로 모델의 테이블을 생성하자! (syncdb는 create만 해주고 alter는 해주지 않는다. 만약에 컬럼명이 변경된 경우 수동으로 고쳐야함)

### API로 놀기

`$ python manage.py shell` managy.py가 DJANGO_SETTINGS_MODULE의 환경을 세팅해줌

“`python
>>> from polls.models import Poll, Choice
>>> Poll.objects.all()
[]

>>> from django.utils import timezone
>>> p = Poll(question=”What’s new?”, pub_date=timezone.now())
>>> p.save()
>>> p.id
1

>>> p.question
“What’s new?”
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=)

>>> p.question = “What’s up?”
>>> p.save()

>>> Poll.objects.all()
[]
“`

마지막에 Poll object라고 나온거는 전혀 도움이 안되니 도움이 되는 문자열로 만들어보자.

polls/models.py 에 다음과 같은 메서드를 추가해주면 됨

“`python
from django.db import models

class Poll(models.Model):
# …
def __unicode__(self): # Python 3: def __str__(self):
return self.question

class Choice(models.Model):
# …
def __unicode__(self): # Python 3: def __str__(self):
return self.choice_text
“`

메서드 하나를 또 추가해보자

“`python
import datetime
from django.utils import timezone
# …
class Poll(models.Model):
# …
def was_published_recently(self):
return self.pub_date >= timezone.now() – datetime.timedelta(days=1)
“`

`python manage.py shell`을 다시실행해서 놀아보자

“`python
>>> from polls.models import Poll, Choice

# Make sure our __unicode__() addition worked.
>>> Poll.objects.all()
[]

>>> Poll.objects.filter(id=1)
[]
>>> Poll.objects.filter(question__startswith=’What’)
[]

# Get the poll that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Poll.objects.get(pub_date__year=current_year)

# Request an ID that doesn’t exist, this will raise an exception.
>>> Poll.objects.get(id=2)
Traceback (most recent call last):

DoesNotExist: Poll matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)

>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
True

>>> p = Poll.objects.get(pk=1)

>>> p.choice_set.all()
[]

>>> p.choice_set.create(choice_text=’Not much’, votes=0)

>>> p.choice_set.create(choice_text=’The sky’, votes=0)

>>> c = p.choice_set.create(choice_text=’Just hacking again’, votes=0)

>>> c.poll

>>> p.choice_set.all()
[, , ]
>>> p.choice_set.count()
3

>>> Choice.objects.filter(poll__pub_date__year=current_year)
[, , ]

>>> c = p.choice_set.filter(choice_text__startswith=’Just hacking’)
>>> c.delete()
“`

여기까지 했으면 인제 파트2로 넘어가도 됨. (튜토리얼은 6개까지 있음)
[/markdown]

[python] private / public아이피 구분하는 스크립트

아이피가 퍼블릭인지 사설아이피인지
구분해야할 필요가 있어서, 쉘스크립트로 만들려고 찾아보다가
포기하고 쉘에서 스크립트언어를 불러오는 방법으로 변경했다.

요즘 루비를 공부중인지라 루비로 만들고 싶었지만,
회사의 서버에는 루비가 거의 설치가 안되어 있는지라

회사의 서버에 대부분 설치 되어 있는 파이썬으로 만들었다.

첨에는 어떻게 해야되는지 좀 막막했는데,
아래 링크의 소스를 보니 그렇게 어렵지 않았다.
파이썬의 소스도 아래링크의 php소스를 파이썬으로 변경한것이다.

Check private IP function PHP

그리고 스택오버플로우에 무지하게 간단한 방법이 있긴했는데,
뭔가 모듈을 설치해야되는것 같았다.
http://stackoverflow.com/questions/691045/how-do-you-determine-if-an-ip-address-is-private-in-python

그래서 그냥 php소스를 python으로 변경하는것으로 최종 결정했다.

아래는 포팅한 소스이다.
파이썬을 잘하는 편이 아닌지라 되도록 간단히 만들려고 노력했다.

원리는 ip를 long타입으로 변환해서 privateip구간에 있는지 체크하는 원리이다.
뭔가 더 좋은게 있을것 같긴한데…(아시는분은 코멘트 좀 부탁드려요.^^)

isPrivateIp.py

import sys
from struct import *
from socket import *

if len(sys.argv) != 2:
    print "input just one parameter."
    sys.exit()

input_ip = sys.argv[1]

private_addrs = ['10.0.0.0|10.255.255.255',
                 '172.16.0.0|172.31.255.255',
                 '192.168.0.0|192.168.255.255',
                 '169.254.0.0|169.254.255.255',
                 '127.0.0.0|127.255.255.255'
                 ]

def ip2long(ip_addr):
    ip_packed = inet_aton(ip_addr)
    ip = unpack("!L", ip_packed)[0]
    return ip

def isPrivateIP(ip_addr):
    long_ip = ip2long(ip_addr)
    if long_ip != -1:
        for private_addr in private_addrs:
            start, end = private_addr.split("|")

            if long_ip >= ip2long(start) and long_ip <= ip2long(end):
                return 'PRIVATE'

    return 'PUBLIC'

print(isPrivateIP(input_ip))

쉘에서 사용하는 경우

IP_TYPE="`python ${DEPLOY_HOME}/isPrivateIp.py $IPADDR`"
echo "IP type is $IP_TYPE"

if [ "$IP_TYPE" == "PRIVATE" ];then
	echo "PIVATE IP!"

fi