일하면서 2 : 파이썬 자료형 조심하자
처음으로 운영성? 유지보수성 업무? 해서 비스무리하게 파악하게되어 정리
일단 문제는 여러개가 들어오던 데이터가 1개만 들어온 날에
(예를들어 실질적인 구분단위가 사람이고 그 안에 주렁주렁 데이터가 있는 형태고, '사람'=name 데이터가 1명만 들어온 케이스)
로그를 보니 갑자기 데이터 인덱싱에러가 난 상황.
그래서 의심점은 그냥 프로그램에러는 아닐것같았고 데이터 형태 문제-> 이전과 똑같이 왔다.
그래서 xml-> dictionary 에서 문제가 일어나거나 dictionary에서 key값 참조해 루프할 리스트 만드는 과정에서 에러 의심 (데이터가 단수개 들어온 상황에서)
결론적으로는 xml -> dictionary에서 하위엘레먼트가 단수/복수개일 경우 차이가 있었고(동일 key값 element가 복수개면 list로 감싸줌) 그래서 loop돌때 자료형 차이로 에러가 발생하는것이었음)
xml to dictionary : element 복수 케이스
input : xml파일
<info>
<name>
<id>1</id>
<id2>1</id2>
</name>
<name>
<id>2</id>
<id2>2</id2>
</name>
<name>
<id>3</id>
<id2>3</id2>
</name>
</info>
대충 이런 xml데이터를 dictionary형태로 바꾸어서 리스트화 =>루프를 도는 코드였다.
import xmltodict
with open(path, 'r', encoding='utf-8') as f: xml_file = xmltodict.parse(f.read(), encoding='utf-8')
received_data = dict(xml_file)
-> data_list = received_data['info']['name']
위와같이 데이터 저장 시 recieved data는
{'info':
OrderedDict([
('name', [
OrderedDict([
('id', '1'),('id2', '1') ]),
OrderedDict([
('id', '2'),('id2', '2') ]),
OrderedDict([
('id', '3'),('id2', '3') ]),
] #key 'name'의 value (list)
) # ('name','value') end 괄호
)] #ordereddict end괄호
}#dictionary end 괄호
위와 같이 저장된다. name의 value가 orderedDict의 List로 저장된다.
json으로 치면
{
"info":
{
"name":{{
{
"id":1,
"id2":1
},
{
"id":2
"id2":2
},
{
"id":3
"id2":3
},
}}/*end name value*/
}/*end info value
}/*end dictionary*/
약간 이런식
name값이 1개만 온다면 ? (내부 element가 1개뿐)
xml to dictionary : element 단수 케이스
<info>
<name>
<id>1</id>
<id2>1</id2>
</name>
</info>
데이터가 위와같이 온다면,
{'info':
OrderedDict([
('name',
OrderedDict([
('id', '1'),
('id2', '1')
])
)
])
}
똑같았다.
확인차 id가 1개뿐인경우도
{'info':
OrderedDict([
('name',
OrderedDict([
('id', '1')
])
)]
)
}
내부 element key:value는 단수:단일값자료형(integer등..)이 아니면 ordereddict로 감싸나온다.
( 단일값자료형이면 ('키','값')으로 아니면 ('키',orderedDict([])) )
의심했던건 단일값 자료형이 아니고 리스트같은 복수값 자료형(list..) 여도, 리스트에 값이 1개만 있다면 OrderedDict로 감싸지 않을 수 있다고 생각했는데, 그건아니었고,
*** ★ name의 value가 orderedDict의 List가 아닌 orderedDict 한개로 저장된다. =>
이부분이 나중에 루프를 돌때 indices 에러 발생시키는 원인이었다.
dictionary 참조 : 복수 element 케이스
data_list = received_data['info']['name']는
received_data['info']=OrderedDict([
('name', [
OrderedDict([
('id', '1'),('id2', '1') ]),
OrderedDict([
('id', '2'),('id2', '2') ]),
OrderedDict([
('id', '3'),('id2', '3') ]),
] #key 'name'의 value (list)
) # ('name','value') end 괄호
)] #ordereddict end괄호
received_data['info']['name']= [
OrderedDict([
('id', '1'),('id2', '1') ]),
OrderedDict([
('id', '2'),('id2', '2') ]),
OrderedDict([
('id', '3'),('id2', '3') ]),
] #key 'name'의 value (list)
) # ('name','value') end 괄호
문제가 되었던 코드는
for a in data_list
something = a['id'] ~~~
대충 이런 코드였는데
저 name value값인 list (orderdDict)가 루프에서 orderdict로 나오게 되어
차례로
idx0 : {"id":1, "id2";1}
idx1 : {"id":2, "id2";2}
idx2 : {"id":3, "id2";3}
요렇게 나온다.
=>각 루프 원소는 dictionary로 key값'id' 참조 가능하다.(정상케이스)
dictionary 참조 : 단수 element 케이스
data_list = received_data['info']['name']
++1개 오는 경우 received_data 다시한번 살펴보면
{'info':
OrderedDict([
('name',
OrderedDict([
('id', '1'),
('id2', '1')
])
)
])
}
이고,
data_list는
received_data['info'] = OrderedDict([
('name',
OrderedDict([
('id', '1'),
('id2', '1')
])
)
])
received_data['info']['name'] =
OrderedDict([
('id', '1'),
('id2', '1')
])
=> data_list=received_data['info']['name'] 를 루프돌게되면
OrderedDict의 원소인
idx0 : ('id', '1'),
idx1 : ('id2', '1')
이렇게 나온다. (데이터로부터 봤을때. (프로그래밍 돌린결과 X)
복수개일때와 비교해보면
#복수
data_list[0]: {"id":1, "id2";1}
data_list[1] : {"id":2, "id2";2}
data_list[2] : {"id":3, "id2";3}
#단수
data_list[0] : ('id', '1'), # (X) , data_list['id']=1 (O)
data_list[1] : ('id2', '1')
이 때 data_list[0]이 단수케이스일경우 가능한가 ?
=> X . 복수개일경우 data_list는 list자료형이지만,
단수개일경우 data_list는 OrderedDictionary이기때문에
data_list[0]은 0인 키값을 찾는것. **(복습하자면 dictionary는 순서가 없다. 인덱싱 X key-val)
이래저래 정리하느라 길게 쓰긴 했는데 결국 단수/복수개 처리가 없었어서 에러가 발생한것이었다.
약간 type선언 안해놓고 쓰는 js나 python에서는 이런 실수가 발생하기 쉽다~ 라고만 듣긴 들었던 것 같아서 스트링 리스트 / 인티저 플롯 / 스트링 인티저 / 쓰기전에 타입한번 확인해보자~ 조심 이정도수준으로만 생각했던거같은데
막상 이번에 업무에서 본 케이스에서 체감됬다고해야하나 그래서 정리해놓음.
Author And Source
이 문제에 관하여(일하면서 2 : 파이썬 자료형 조심하자), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jeongsunyong/잡지식2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)