흔한생각 (recording)/Dynamo

Dynamo Python 노드에서 PyPI 패키지 사용하기

hnanmal 2022. 5. 12. 00:39
300x250

 

2022.05.13 - 내용추가

깜박하고 중요한 걸 설명에서 빼먹었네요.

밑의 예제에서 사용된 파이썬 노드들은 모두 Python Engine Version을 CPython 모드로 설정해야 합니다!...

그 이유는

1. IronPython이 Python 3.xx버전을 지원하지 않음. (따라서 python 2의 문법을 써야하는데, 3 배우기도 바쁜 시대에 좀 불합리하죠?)

2. 거의 대부분의 유용한 패키지들이 CPython 구현체를 기반으로 작성되어있음.(IronPython의 경우에는 호환되지 않는 경우가 대부분)

이기 때문입니다.

그리고 어차피 다이나모 버전이 올라감에 따라 IronPython 엔진은 deprecate 될 예정이니, 지금부터 아예 CPython 모드로만 작성하는 습관을 들이시길 권합니다....!!!

 

 

 

 

이 글은 하기 링크의 글과 함께 보면 더 유용할 수 있습니다.
https://hnanmal.tistory.com/entry/다이나모-파이썬-노드에서-임의로-설치한-패키지-사용하기

 

다이나모 파이썬 노드에서 임의로 설치한 패키지 사용하기

다이나모를 쓰다 보면 캔버스 공간 효율화와, 코드 단순화를 목적으로 파이썬 노드를 쓰게 되는 경우가 왕왕 있습니다. 그런데 파이썬으로 모든 기능을 구현하려면 흔히 말하는 ‘바퀴를 새로

hnanmal.tistory.com



레빗에서 >> 그 위에서 실행된 다이나모에서 >> 또 그 안에서 작동하는 파이썬 스크립트 노드의 활용성을 극대화시키는 팁에 대한 내용입니다.

일단, PyPI를 아십니까?

파이썬에서는 고수들이 만들어 놓은 패키지를 사용해서 좀더 효율적인 코딩을 할 수 있습니다.
그런 패키지들이 정식으로 모여있는 곳이 바로 PyPI인데요.
https://hnanmal.tistory.com/entry/python-pip가-뭔데-이렇게-편하냐고요
긴 설명을 하기 어려우니 Python Package Index (PyPI)에 대한 설명은 위 링크로 대신할게요.

간단히 말하면, 파이썬에서는 cmd 창에서의 간단한 입력을 통해 남이 만든 패키지를 설치할 수 있고, (위 그림에서 적색 박스처럼요. 1초면 끝납니다.)
코드 내부에서는 import 명령어를 통해 이를 쉽게 사용할 수 있습니다.
이런 좋은 방법이 있으면 당연히 활용해서 코드를 짜는 게 좋겠죠?


다이나모에서 PyPI를 쓰는 법을 아십니까?

그런데, 레빗 >> 다이나모 >> 파이썬 노드의 복잡 다단 한 실행환경을 거치는 우리의 상황에서는 파이썬에 설치된 패키지라고 해도, 다이나모에서 작성된 파이썬 노드에서는 호출해서 쓰기가 조금은 까다롭습니다.
그래도 방법이 없는 건 아닙니다.

지금부터 방법을 살펴볼 건데, 저는 엑셀을 읽어 들이는데 자주 쓰는 OpenpyXl이라는 패키지를 사용해 볼 예정입니다.

방법을 요약하자면, 일반적인 파이썬 환경과 동일하게,
import openpyxl 이라는 명령어를 통해 패키지를 로드할 거고요.

그렇게 하기 위해 몇 줄(정확히는 12줄) 선행되어야 하는 코드가 있습니다.
이 선행 코드의 원리는, 환경변수를 통해 컴퓨터마다 달라지는 사용자의 파이썬 패키지 경로를 일원화하는 것인데요. 자세한 건 스크린샷과 함께 보시죠.

(혼자서만 쓰는 . dyn 파일을 만들고 싶으시면 선행 코드는 1줄이면 됩니다.)


선행코드 작성에 앞서 환경변수와 파이썬 설치경로 잠깐만 이해하고 갑시다.

 

결론적으로 선행 코드에 포함시켜야 하는 경로는 위의 스크린샷과 같습니다. 어딘가 깊숙이 들어있죠?

문제는 저 빨간색 “사용자 명”부분과 보라색 박스의 파이썬 버전명으로 된 경로 부분은 컴퓨터마다 달라지기 쉽다는 것입니다. 모든 컴퓨터에서 패키지 설치 경로가 동일하다면 사실 이런 잔머리를 쓸 이유도 없겠죠?

일단은 빨간색 “사용자 명” 부분을 하나의 통일된 이름으로 접근하고 싶을 때 사용하는 것이 환경변수라고 설명하겠습니다. 환경변수가 무엇인지는 구글에 검색해서 정의를 살펴보시고, 여기서는 일단 탐색기를 통해 설명할게요.

위 그림처럼 %LOCALAPPDATA% 라고 탐색기 주소창에 작성하고 엔터를 누르면 어떻게 될까요?


그러면 곧바로 위와 같이
C:\Users\ex\AppData\Local
의 경로로 이동하게 됩니다.

저 빨간 ex 부분은 컴퓨터가 달라지면 당연히 바뀌겠죠?
하지만 바뀐 컴퓨터에서도 %LOCALAPPDATA%를 입력하면 동일한 개념의 폴더로 이동하게 됩니다.
우리 선행 코드는 바로 이 점을 활용할 겁니다.


본격적인 코드 작성: 환경변수 활용

레빗을 켜고 빈 프로젝트 열어주고, 다이나모 창도 새로 열어줍니다. 그리고 파이썬 노드 하나 만들어주세요.


그다음 열린 창에 다음과 같이 4개의 파이썬 기본 모듈을 로드해 줍니다. (각각의 용도는 코드 설명하면서 자연스럽게 아실 거예요.)


그리고 위 코드를 통해 파이썬의 데이터가 설치되는 기본 경로를 잡아줍니다. 좌측에 python_rootpath변수에 담긴 값이 출력되는 것도 보이시죠?

 
















Programs\python 폴더 하위에는 설치한 버전의 숫자명이 포함된 하위 폴더가 있습니다.


최신 버전 파이썬 폴더 구분하기

 

os.listdir( ) 메서드를 통해 Python폴더 내부에 있는 모든 폴더 목록을 한번 출력해 볼까요?
Python310이라고 출력되는 걸 볼 수 있습니다. 여러 가지의 파이썬 버전이 깔린다면, 출력되는 목록도 한 개 이상이 되겠죠?


그런데 위쪽의 스크린샷에서는 주소창의 보라색 박스에 분명 Python39라고 쓰여있었는데 이상하다고 느끼셨죠? 사실 이 포스팅을 두 개의 컴퓨터를 오가며 작업하고 있기 때문에 그렇습니다.

위쪽에서 사용한 컴퓨터에는 파이썬 3.9 버전이 깔려있었고, 지금 이 컴퓨터에는 파이썬 3.10 버전이 깔려있기 때문에 폴더명도 달라진 것이죠.


하지만 그렇다 하더라도 문제가 없도록 코드를 짜는 것이 목표입니다~.


정규표현식을 사용해서 혹시나 Python폴더의 내부에 다른 종류의 폴더가 추가로 생기는 상황을 고려해 필터링해 줄 필요가 있습니다.

아까 보니 버전에 따라서 PythonXX의 형태로 폴더명이 정해졌죠?
해당 형식이 아닌 폴더들은 걸러주고, version_list라는 변수에 저장해둡시다.


기존의 파이썬을 지우지 않고, 신규 버전의 파이썬을 설치한 사람의 컴퓨터인 경우에는
Python39, Python310 이렇게 2개 이상의 폴더가 있을 수 있습니다. 이중 최신 버전의 파이썬에 설치된 패키지를 참조한다고 가정하고 코드를 짜 볼게요.


더미 폴더를 추가하고 python 폴더의 하위 폴더를 다시 검색하니 2개의 폴더명이 잘 나옵니다.


파이썬 버전의 최신을 판별하는 것은 뒤쪽의 마이너 버전 숫자 부분이니 따로 떼어냅시다.


숫자가 가장 큰 폴더가 몇 번째 폴더인지를 검색하여 인덱스 번호로 저장합시다.


자 이렇게 하면 가장 최신의 파이썬 버전이 Python310 폴더라는 것을 저장해 둘 수 있습니다.

(여기에 있는 최신 버전 검색 방법은 결코 완전하지 않고, 예시를 위해 급조된 방법임을 알려드립니다. 실제로는 메이저 버전 숫자가 다른 폴더가 혼재되어 있는 경우 등을 포함해서 더 엄밀한 처리를 하여야 하지만, ‘간단한 코드로 당분간은 편하게 쓸 수 있는 코드를 작성했다.’라고 이해하시면 될 것 같습니다.)


이제 sys.path에 append메서드로 우리가 찾아낸 경로를 추가하기만 하면 준비가 끝납니다.
import openpyxl 이라고 작성하고 실행하니, 자연스럽게 모듈이 임포트 됩니다!!


엑셀 파일을 준비해서 openpyxl모듈의 사용법도 일부 보여드리고 싶지만, 그것은 추후 별도 포스팅하기로 하고, 이번에는 dir함수를 통해 openpyxl모듈이 어떤 요소로 구성되어 있는지만 확인하고 마치겠습니다. 정상적으로 잘 import 된 것이고, 저는 개인적으로 엑셀 출력까지도 openpyxl을 활용해서 다이나모 코드를 구성하고 있는데 잘 작동됩니다.

다이나모 기본 노드에 있는 ExportExcel, ImportExcel 노드를 쓰지 않는 이유는,

  1. 느린 속도
  2. 엑셀에 기입된 수식을 그 자체로 읽을 수 없는 점
  3. 출력 시 엑셀 서식을 적용할 수 없다는 점


이런 3가지 이유 때문입니다.



<전체 코드>

# Load the Python Standard and DesignScript Libraries
import os
import sys
import re
import clr

python_rootpath = os.getenv('LOCALAPPDATA')+'\Programs\Python'
python_dir_list = os.listdir(python_rootpath)

p = re.compile('Python\d{2,5}')
version_list = list(filter(lambda x: p.match(x), python_dir_list))
version_num = list(map(lambda x: int(x[7:]), version_list))
latest_idx= version_num.index(max(version_num))

python_version = version_list[latest_idx]

sys.path.append(os.getenv('LOCALAPPDATA').replace('\\','\\\\') + f'\Programs\Python\{python_version}\Lib\site-packages')

import openpyxl

# Assign your output to the OUT variable.
OUT = dir(openpyxl)

 

만약 여럿이 공유하는 다이나모 파일을 만든다면 주석으로 저렇게 안내해 주는 것도 좋을 것 같습니다.




다음에는 openpyxl 사용 사례를 가지고 다시 글 올리겠습니다~

반응형