저는 AI에게 비동기적으로 이미지를 다운로드하는 Python asyncio를 작성해 달라고 요청했습니다.
이미지를 다운로드할 수 있지만, 저장하지 않고 이미지 바이너리 파일을 JMP 테이블에 직접 쓰는 방법은 모르겠습니다.
전문가 여러분 감사합니다!
JMP 18에서는 JSL만이 이미지를 테이블에 넣는 스크립트를 만들 수 있습니다.
나는 이전에 AI에게 이런 방식으로 JSL을 호출하라고 경고했습니다.
jmp.run_jsl = '''
dt = Data Table("ImageTable");
dt[{i + 1}, "Image"] = New Image(Open("{data_url}"));
'''
알아내려는 사람이 있나요? 흰색 텍스트는 파이썬입니다. 빨간색 텍스트는 jsl입니다. 파이썬 형식은 빨간색 jsl 문자열(세 개의 따옴표로 구분)의 {}를 두 개의 매개변수로 바꿉니다. base64data는 base64로 인코딩된 png 또는 jpg 파일의 바이너리 데이터이며, 이것이 newimage에 필요한 것입니다.
유일하게 놀란 부분은 두 언어를 섞는 부분인데, 라라가 다음 게시물에서 거의 정확한 해결책을 제안했지만요.
AI에게 물어보니 분석이 나왔어요:(grok3)
다운로드한 이미지 데이터를 JMP 데이터 테이블에 쓰는 코드 세그먼트에 대한 자세한 영어 설명은 다음과 같습니다.
# Write results to JMP data table
for i, (url, image_data) in enumerate(results):
if image_data:
dt["URL"][i] = url
# Encode binary data to base64 and create a Blob object
base64_data = base64.b64encode(image_data).decode('utf-8')
# Create an image object using JSL's CharToBlob
jsl_code = '''
dt = Data Table("ImageTable");
dt[{} , "Image"] = New Image(CharToBlob("{}", "base64"));
'''.format(i + 1, base64_data)
jmp.run_jsl(jsl_code)print("모든 이미지가 JMP 테이블에 기록되었습니다!")
줄별 설명
i에 대해 (url, image_data) in enumerate(results):
results는 asyncio.gather(*tasks)가 반환하는 튜플의 목록이며, 각 튜플에는 (url, image_data)가 포함됩니다.
url은 이미지의 소스 URL(문자열)입니다.
image_data는 이미지의 바이너리 데이터(바이트)이고, 다운로드가 실패하면 None입니다.
enumerate(results)는 각 튜플에 대해 인덱스 i(0부터 시작)를 제공하며, 이는 JMP 데이터 테이블의 행을 지정하는 데 사용됩니다.
이 줄은 모든 다운로드 결과를 반복하여 유효한 데이터를 테이블에 쓸 준비를 합니다.
image_data의 경우:
image_data가 None이 아닌지 확인하고, 성공적으로 다운로드된 이미지만 처리되도록 합니다.
다운로드가 실패하면(image_data가 None인 경우), 루프는 다음 반복으로 건너뛰어 후속 단계에서 오류가 발생하는 것을 방지합니다.
dt["URL"][i] = url
dt는 jmp.DataTable("ImageTable")을 사용하여 생성한 JMP 데이터 테이블 객체입니다.
dt["URL"]은 데이터 테이블의 "URL" 열에 액세스합니다. 이 열의 데이터 유형은 jmp.DataType.Character(문자 유형)입니다.
dt["URL"][i]는 "URL" 열의 i번째 행(0부터 시작하는 인덱싱)에 url(이미지의 소스 주소)을 할당합니다.
이 단계에서는 JMP Python API를 직접 사용하여 셀 값을 설정하고 이미지의 원점을 기록합니다.
base64_data = base64.b64encode(이미지_데이터).decode('utf-8')
base64.b64인코드(이미지 데이터):
이진 이미지 데이터(image_data, 바이트 객체)를 base64 형식으로 인코딩하여 바이트 문자열을 반환합니다.
Base64는 이진 데이터를 ASCII 문자열로 변환하는 방법으로, 텍스트 기반 환경에 적합합니다.
.decode('utf-8'):
base64 바이트 문자열을 UTF-8로 인코딩된 문자열로 디코딩하여 일반 텍스트 base64 표현(예: "iVBORw0KGgo...")을 생성합니다.
이 단계에서는 바이너리 이미지 데이터를 JSL이 처리할 수 있는 문자열 형식으로 변환합니다.
jsl_코드 = '''...'''
JSL(JMP 스크립팅 언어) 스크립트를 문자열로 정의하여 이미지 객체를 생성하고 데이터 테이블에 할당합니다.
스크립트 내용:
dt = Data Table("ImageTable");
dt[{} , "Image"] = New Image(CharToBlob("{}", "base64"));dt = Data Table("ImageTable");:
JSL에서 "ImageTable" 데이터 테이블을 검색하여 올바른 테이블이 타겟으로 지정되었는지 확인합니다.
dt[{} , "이미지"]:
{}는 i + 1로 대체되는 플레이스홀더로, 행 번호를 나타냅니다(JSL은 1부터 시작하는 인덱싱을 사용하므로 i + 1이 사용됩니다).
"이미지"는 대상 열 이름을 지정합니다.
새 이미지(CharToBlob("{}", "base64")):
CharToBlob("{}", "base64"):
base64로 인코딩된 문자열(두 번째 {}에서 base64_data로 대체)을 바이너리 데이터(Blob)로 변환합니다.
"base64"는 입력 문자열이 base64 형식임을 JSL에 나타냅니다.
새로운 이미지(...):
JMP의 "표현식" 열 유형과 호환되는 이진 데이터에서 이미지 객체를 만듭니다.
.format(i + 1, base64_data):
Python의 문자열 형식을 사용하여 i + 1(행 번호)과 base64_data(base64 문자열)를 JSL 스크립트에 삽입합니다.
예: i = 0이고 base64_data = "iVBORw0KGgo..."인 경우 결과 jsl_code는 다음과 같습니다.
dt = Data Table("ImageTable");
dt[1 , "Image"] = New Image(CharToBlob("iVBORw0KGgo...", "base64"));
jmp.run_jsl(jsl_코드)
jmp.run_jsl은 JSL 스크립트를 실행하는 JMP Python API 함수입니다.
생성된 jsl_code를 JMP에 전달하여 다음을 수행합니다.
"ImageTable" 데이터 테이블의 행 i + 1의 "Image" 열에 이미지 객체를 삽입합니다.
이미지 객체는 base64_data에서 파생되며 JMP에서 볼 수 있는 이미지로 표시됩니다.
print("모든 JMP 파일이 포함되어 있습니다!")
루프가 완료되면 중국어로 "모든 이미지가 JMP 테이블에 기록되었습니다!"라는 메시지가 출력됩니다.
이는 작업 완료를 확인하는 간단한 상태 알림 역할을 합니다.
작동 원리
데이터 흐름:
결과에서 각 이미지의 url과 image_data를 검색합니다.
"URL" 열에 url을 직접 씁니다.
image_data를 base64 문자열로 인코딩합니다.
JSL을 사용하여 base64 문자열을 이미지 객체로 변환하고 "Image" 열에 씁니다.
주요 기술:
asyncio: 비동기 이미지 다운로드를 처리합니다.
base64: 이진 데이터를 문자열로 인코딩합니다.
JSL: CharToBlob과 New Image를 사용하여 JMP에서 이미지를 처리합니다.
JMP Python API: jmp.run_jsl을 통해 Python과 JSL을 연결합니다.
참고사항:
"이미지" 열은 이미지 객체를 저장하기 위해 jmp.DataType.Expression 유형이어야 합니다.
JSL은 1부터 시작하는 행 인덱싱을 사용하는 반면, Python의 열거형은 0부터 시작하므로 i + 1이 됩니다.
오류를 방지하기 위해 image_data가 None인 경우 처리를 건너뜁니다.
잠재적 개선 사항
오류 처리: JSL 실행 오류를 포착하기 위해 jmp.run_jsl(jsl_code) 주위에 try-except 블록을 추가합니다.
성능: 이미지 수가 많은 경우 행별 호출 대신 일괄 JSL 실행을 사용합니다.
디버깅: 문제 해결을 위해 base64_data 또는 jsl_code를 기록합니다.
이 코드는 디스크에 저장하지 않고 메모리의 이미지 데이터를 JMP 데이터 테이블에 성공적으로 씁니다.
저는 JSL의 New Multi HTTP Request()보다 Python의 asyncio 비동기 다운로드 속도가 훨씬 빠르다는 것을 여러 번 시도해 보았습니다.