IPython과 셸 명령어
표준 파이썬 인터프리터로 작업할 때 가장 번거로운 점 중 하나는, 파이썬 도구와 시스템 커맨드 라인 도구를 번갈아 사용하기 위해 여러 창을 오가야 한다는 사실입니다. IPython은 이러한 불편함을 해소하기 위해 터미널 내에서 직접 셸 명령어를 실행할 수 있는 구문을 제공합니다. 마법은 느낌표(!) 하나로 시작됩니다. 한 줄에서 ! 뒤에 오는 모든 내용은 파이썬 커널이 아니라 시스템 커맨드 라인에서 실행됩니다.
이어지는 내용은 리눅스(Linux)나 맥OS(macOS) 같은 유닉스 계열 시스템을 기준으로 설명합니다. 윈도우(Windows)에서는 기본 셸 환경이 달라 일부 예제가 작동하지 않을 수 있지만, ’Linux용 Windows 하위 시스템(WSL)’을 사용한다면 문제없이 실행될 것입니다. 셸 명령어 사용법이 생소하다면, Software Carpentry Foundation에서 제공하는 훌륭한 유닉스 셸 튜토리얼을 참고해 보시기 바랍니다.
셸에 대한 간단한 소개
셸, 터미널, 커맨드 라인 사용법을 이 장에서 모두 다루기는 어렵지만, 입문자를 위해 핵심 내용을 간단히 소개하겠습니다. 셸은 텍스트를 통해 컴퓨터와 상호작용하는 수단입니다. 1980년대 중반 마이크로소프트와 애플이 그래픽 기반 운영체제를 선보인 이후, 대부분의 사용자는 메뉴 선택이나 드래그 앤 드롭 같은 동작에 익숙해졌습니다. 하지만 운영체제는 이러한 그래픽 인터페이스가 나오기 전부터 존재했으며, 주로 텍스트 입력을 통해 제어되었습니다. 즉, 사용자가 프롬프트에 명령을 입력하면 컴퓨터가 그에 맞춰 동작하는 방식이었습니다. 이러한 초기 프롬프트 시스템은 오늘날 데이터 과학자들이 즐겨 쓰는 셸과 터미널의 전신이기도 합니다.
셸이 익숙하지 않은 분들은 아이콘이나 메뉴 클릭으로 똑같은 결과를 얻을 수 있는데 왜 굳이 텍스트를 입력해야 하는지 의문이 들 수도 있습니다. 하지만 셸에 익숙한 사용자들은 반대로 묻습니다. 텍스트 몇 자만 치면 끝날 일을 왜 번거롭게 아이콘과 메뉴를 찾아다녀야 하느냐고요. 취향의 차이처럼 보일 수도 있지만, 기본적인 작업을 넘어서는 복잡한 제어가 필요할 때 셸은 훨씬 더 강력한 힘을 발휘합니다. 물론 처음 익히는 데는 약간의 노력이 필요합니다.
다음은 사용자가 디렉터리와 파일을 탐색하고 수정하는 리눅스/맥OS 셸 세션의 예시입니다. (osx:~ $는 프롬프트이고, $ 뒤의 내용은 입력한 명령어입니다. # 뒤의 내용은 설명을 덧붙인 것입니다.)
``bash osx:~ $ echo “hello world” # echo는 파이썬의 print 함수와 비슷합니다. hello world
osx:~ $ pwd # pwd = 현재 작업 디렉터리 경로 출력 /home/jake # 현재 위치한 경로입니다.
osx:~ $ ls # ls = 현재 디렉터리의 내용물 나열 notebooks projects
osx:~ $ cd projects/ # cd = 디렉터리 변경
osx:projects $ pwd /home/jake/projects
osx:projects $ ls datasci_book mpld3 myproject.txt
osx:projects $ mkdir myproject # mkdir = 새 디렉터리 생성
osx:projects $ cd myproject/
osx:myproject $ mv ../myproject.txt ./ # mv = 파일 이동. # 상위 디렉터리(..)에 있는 myproject.txt 파일을 # 현재 디렉터리(./)로 옮깁니다.
osx:myproject $ ls myproject.txt
이 모든 과정은 아이콘을 클릭하는 대신 명령어를 입력하여 디렉터리를 탐색하고 만들고 파일을 옮기는 익숙한 작업들입니다.
`pwd`, `ls`, `cd`, `mkdir`, `cp` 같은 명령어 몇 가지만 알면 일상적인 파일 작업을 대부분 처리할 수 있으며, 이 기초를 넘어서면 셸의 진정한 강력함을 경험하게 될 것입니다.
## IPython의 셸 명령어
앞서 언급했듯이, 모든 표준 셸 명령어는 앞에 `!` 문자를 붙여 IPython에서 바로 실행합니다.
예를 들어 `ls`, `pwd`, `echo` 명령어는 다음과 같이 실행합니다.
``ipython
In [1]: !ls
myproject.txt
In [2]: !pwd
/home/jake/projects/myproject
In [3]: !echo "셸에서 출력 중"
셸에서 출력 중
셸과 값 주고받기
IPython에서 셸 명령어를 호출할 수 있을 뿐만 아니라, IPython의 변수나 데이터와 서로 상호작용하게 만들 수도 있습니다. 예를 들어 할당 연산자(=)를 사용해 셸 명령어의 실행 결과를 파이썬 리스트에 저장합니다.
``ipython In [4]: contents = !ls
In [5]: print(contents) [‘myproject.txt’]
In [6]: directory = !pwd
In [7]: print(directory) [‘/Users/jakevdp/notebooks/tmp/myproject’]
엄밀히 말하면 이 결과값은 일반 리스트가 아니라 IPython이 정의한 특수한 형태의 반환 타입입니다.
``ipython
In [8]: type(directory)
IPython.utils.text.SList
이 객체는 파이썬 리스트와 거의 비슷하게 작동하면서도 몇 가지 유용한 추가 기능을 제공합니다. 결과를 편리하게 검색, 필터링, 표시할 수 있는 grep 및 fields 메서드와 s, n, p 속성이 포함되어 있습니다. 자세한 내용은 IPython의 내장 도움말 기능을 활용해 보시기 바랍니다.
반대로 파이썬 변수를 셸로 전달하고 싶을 때는 {varname} 구문을 사용하면 됩니다.
``ipython In [9]: message = “파이썬에서 보내는 메시지”
In [10]: !echo {message} 파이썬에서 보내는 메시지
중괄호 안에 변수 이름을 넣으면, 셸 명령어가 실행될 때 해당 변수의 내용물로 치환됩니다.
## 셸 관련 매직 명령어
IPython에서 셸 명령어를 조금 사용해 보다 보면, `!cd`를 써서는 파일 시스템을 마음대로 이동할 수 없다는 사실을 알게 됩니다.
``ipython
In [11]: !pwd
/home/jake/projects/myproject
In [12]: !cd ..
In [13]: !pwd
/home/jake/projects/myproject
그 이유는 주피터 노트북의 셸 명령어가 명령어마다 상태를 유지하지 않는 임시 하위 셸에서 실행되기 때문입니다. 현재 작업 디렉터리를 지속적으로 변경하고 싶다면 %cd 매직 명령어를 사용해야 합니다.
``ipython In [14]: %cd .. /home/jake/projects
실제로는 기본 설정상 `%` 기호 없이도 사용합니다.
``ipython
In [15]: cd myproject
/home/jake/projects/myproject
이것을 오토매직(Automagic) 기능이라고 부르며, % 없이 명령어를 실행할지 여부는 %automagic 명령으로 설정합니다.
%cd 외에도 %cat, %cp, %env, %ls, %man, %mkdir, %more, %mv, %pwd, %rm, %rmdir 등 셸 명령어와 비슷한 다양한 매직 함수가 있습니다. 오토매직이 켜져 있다면 % 기호 없이도 사용할 수 있어, IPython 프롬프트를 마치 일반 셸처럼 다룰 수 있습니다.
``ipython In [16]: mkdir tmp
In [17]: ls myproject.txt tmp/
In [18]: cp myproject.txt tmp/
In [19]: ls tmp myproject.txt
In [20]: rm -r tmp ````
이처럼 파이썬 세션 안에서 셸 환경에 바로 접근할 수 있게 되면, 맥락을 전환하는 번거로움 없이 파이썬과 셸을 훨씬 자연스럽게 결합해 작업합니다.