0

내가 API를 쿼리 다음과 같은 값으로 JSON의 덩어리 얻을 :파이썬 2.7을 사용하여 sqlite3 데이터베이스에 유니 코드 문자를 삽입 할 때 추가 이스케이프 문자가 왜 발생합니까?

{ 
    ... 
    "Attribute" : "Some W\u00e9irdness", 
    ... 
} 

(올바른 값은 물론, '일부 불확실성'이다)

좀 다른 것들과 함께 그 값을 추가 내 sqlite3 데이터베이스에 추가 할 필드 목록. 목록은 다음과 같습니다

[None, 203, None, None, True, u'W\xe9irdness', None, u'Some', None, None, u'Some W\xe9irdness', None, u'Some W\xe9irdness', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] 

나는 우리가 이미 xe9을 \에 \ x00e9에서 스위치를 시행 한 것을 알, 그리고 아직 이유를 잘 모르겠어요,하지만 난 그게 중요하지 않았다 기대했다 ... 그것은 다른 유니 코드 인코딩 일뿐입니다.

, 나는 목록을 'stringatize'sqlite가 테이블에 삽입하기 전에 (아래 기능 참조) 그것을 튜플합니다

my_tuple = tuple(val for val in my_utils.stringatize(my_list)) 

sql = "INSERT OR REPLACE INTO roster VALUES %s" % repr(my_tuple) 

cur.execute(sql) 

: 다음 삽입을

('', '203', '', '', 'True', 'W\xe9irdness', '', 'Some', '', '', 'Some W\xe9irdness', '', 'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '') 

을 나중에 SELECT 문을 사용하여 검색 할 때 값에 추가 이스케이프 (백 슬래시) 문자가 추가되었습니다.

u'Some W\\xe9irdness' 

먼저, sqlite에서 문자열 보간을 사용하지 않아도된다는 것을 이미 알고 있습니다. 그러나, 나는 그것을 어떻게 할 지 알 수 없었습니다. 레코드 당 필드의 수가 시간에 따라 변할 수 있고, 코드를 유연하게하고 싶을 때, 되돌아 와서 거기에 물음표를 추가 할 필요가 없을 때 전지. (당신이 할 수있는 더 좋은 방법을 알고 있다면, 나는 모든 귀 해요,하지만 그것은 다른 게시물에 대한 아마.)

이 문제를 해결하려면, 나는 형식의 삽입 SQL 문을 인쇄하고 난 단지 ONE 백 슬래시 참조 :

INSERT OR REPLACE INTO roster VALUES ('', '203', '', '', 'True', 'W\xe9irdness', '', 'Some', '', '', 'Some W\xe9irdness', '', 'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '') 

위의 목록에서 본 것과 같은 방식이므로 당황 스럽습니다. 아마도 이것은 백 슬래시가 이스케이프 처리되어야하고 xe9가 아스키 텍스트로 처리되는 문자열로 해석됩니다. 나는이 전면에 당신이 나에 대해 가지고있는 아이디어를 주셔서 감사합니다

def stringatize(cell_list, encoding = 'raw_unicode_escape', delete_quotes = False): 
    """ 
    Converts every 'cell' in a 'row' (generally something extracted from 
    a spreadsheet) to a unicode, then returns the list of cells (with all 
    strings now, of course). 
    """ 

    stringatized_list = [] 

    for cell in cell_list: 
     if isinstance(cell, (datetime.datetime)): 
      new = cell.strftime("%Y-%m-%dT%H:%M:%S") 
     elif isinstance(cell, (datetime.date)): 
      new = cell.strftime("%Y-%m-%d") 
     elif isinstance(cell, (datetime.time)): 
      new = cell.strftime("%H:%M:%S") 
     elif isinstance(cell, (int, long)): 
      new = str(cell)  
     elif isinstance(cell, (float)):  
      new = "%.2f" % cell 
     elif cell == None: 
      new = ""  
     else:     
      new = cell  

     if delete_quotes:  
      new = new.replace("\"","") 

     my_unicode = new.encode(encoding)  
     stringatized_list.append(my_unicode) 

    return stringatized_list 

: 저는 여기에 삽입 할 목록을 준비하기 위해 사용하고있어 stringatize 기능입니다. 개체는 결국이 값을 유니 코드로 작동하는 Excel 시트에 덤프하는 것이므로 값을 올바르게 표시해야합니다.

EDIT : @ CL의 질문에 대한 응답으로, 나는 stringatize 함수에서 'encode'줄을 제거하려고합니다. 다음과 같이

은 이제 끝 :

#my_unicode = new.encode(encoding) 
    my_unicode = new 

    stringatized_list.append(my_unicode) 

return stringatized_list 

(나는 그것을 실행하려고 할 때 아래 내가 할 역 추적있다) 새로운 SQL 아웃이처럼 보이는 온다 :

INSERT OR REPLACE INTO roster VALUES ('', u'203', u'', u'', 'True', u'W\xe9irdness', '', u'Some', '', '', u'Some W\xe9irdness', '', u'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '') 

Traceback (most recent call last): 
    File "test.py", line 80, in <module> 
    my_call 
    File redacted.py, line 102, in my_function 
    cur.execute(sql) 
sqlite3.OperationalError: near "'203'": syntax error 

내가 한을 그 숫자를 문자열로 변환하는 것을 의미합니다. 나는 그것이 내가하고있는 repr (my_tuple)과 실제로는 더 이상 유니 코드를 상징하지 않는다고 생각한다.

+0

왜 '인코딩'을 호출하는지, 즉 왜 이것이 필요하다고 생각하십니까? –

+0

@ CL, 나는 그것을 시도하지 않고 바닥을 업데이트했습니다. 이것은 내가 처음 엔 인코딩을 추가 한 이유를 상기시켜주었습니다 ...이 에러를 피하려면 (더 좋은 방법이 있다고 쉽게 추측 할 수 있지만). – HaPsantran

답변

2
"Some W\u00e9irdness" 
"Some Wéirdness" 

정확히 같은 값, Some Wéirdness의 동등-유효한 JSON 문자열 리터럴 형태이다.

u'W\xe9irdness' 

나는 우리가 이미 xe9을 \에 \ x00e9에서 스위치를 시행 한 것을 알, 그리고 아직 이유를 잘 모르겠어요,하지만 난 그게 중요하지 않았다 기대했다 ... 그건 다른 유니 코드 인코딩.

스위치가없고 인코딩도없고 문자열은 여전히 ​​Some Wéirdness입니다.

방금 ​​파이썬에서 문자열을 인쇄했으며 파이썬 문자열 리터럴에 JSON에없는 \xNN 형식이 있으며 \u00NN의 약어입니다.

my_tuple = tuple(val for val in my_utils.stringatize(my_list)) 
sql = "INSERT OR REPLACE INTO roster VALUES %s" % repr(my_tuple) 
cur.execute(sql) 

이 작업을 수행하지 마십시오. repr에 의해 생성 된 파이썬 튜플 리터럴은 SQL 값 목록과 완전히 같은 형식이 아닙니다. 특히 SQL 문자열 리터럴에는 백 슬래시 이스케이프에 대한 개념이 없기 때문에 \xE9은 파이썬 유니 코드 문자열 리터럴에서 é을 나타내는 것으로, 단지 백 슬래시를 의미하며 x, E 및 숫자는 9입니다.

SQL 문자열 리터럴에 맞게 문자열을 인코딩하는 적절한 방법이 있지만 올바른 방법을 얻는 것이 쉽지 않으며 잘못 이해하는 것이 보안 문제이므로 피해야합니다. 대신 '문자열 형식 지정'을 잊어 버리고 원시 값을 매개 변수로 데이터베이스에 전달하십시오.

cur.execute(
    'INSERT OR REPLACE INTO roster VALUES (?, ?, ?, ?, ....)', 
    my_list 
) 
+0

감사합니다. 추가해야 할 정확한 값의 수를 알 필요가없는 방법이 있습니까? 데이터베이스에 필드를 추가 할 때 (자주),이 코드로 돌아와 다른 "?"을 추가하지 않아도되기를 희망합니다. – HaPsantran

+1

가장 간단하게 '% VALUES %', '.join (['? '] * len (my_list))'와 같이 자동으로 쿼리를 생성합니다. 이것이 더 복잡해지기 시작하면 데이터 액세스 레이어/ORM을 고려하는 것이 좋습니다. – bobince

+0

고마워요, @bobince. 이것은 도움이되었다. 나는 그것을 생각해야했다! – HaPsantran