2017-04-23 20 views
7

Tôi đang làm việc trên ứng dụng Flask có postgres/SQLAlchemy/Flask-Admin. Tuy nhiên, trong giao diện Quản trị, mọi lỗi DB có chứa các chữ cái Unicode không thể được báo cáo vì unicode(exc) tăng UnicodeDecodeError.SQLAlchemy Unicode Các vấn đề trong trường hợp ngoại lệ

tôi đã có thể xác định vị trí vấn đề đó để sqlalchemy.exc

class StatementError(SQLAlchemyError): 
    ... 
    def __unicode__(self): 
     return self.__str__() 

Và tạo lại vấn đề bằng với:

class A(Base): 
    __tablename__="a" 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    name2 = Column(String, nullable=False) 

session = Session() 
a = A(name=u"עברית") 
session.add(a) 

try: 
    session.commit() 
except Exception as e: 
    print(repr(e)) 
    print("------------------") 
    print(unicode(e)) 

nào trả về:

ProgrammingError('(psycopg2.ProgrammingError) column "name" of relation "a" does not exist\nLINE 1: INSERT INTO a (name, name2) VALUES (\'\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa\', NULL) RETURNING...\n      ^\n',) 
------------------ 
Traceback (most recent call last): 
    File "test.py", line 27, in <module> 
    print(unicode(e)) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 118: ordinal not in range(128) 

Và Tôi hiện giải quyết nó bằng cách thay thế các ngoại lệ có liên quan với các lớp học của tôi giải mã từ utf-8. Tuy nhiên, đây là một hack khủng khiếp, và tôi đang tìm một giải pháp thích hợp:

  • Có cách nào để cấu hình SQLAlchemy tự động giải mã các thông báo lỗi nhận được không?
  • Có cách để cấu hình Postgres để thông điệp đầu ra trong latin mã hóa (kém thuận lợi, nhưng accetable)
  • Có cách để làm cho unicode cố gắng để giải mã bởi utf-8 thay vì ascii/latin?
  • Có cách nào để giải quyết nó không?

(Vấn đề là chỉ có liên quan đến python2. Trong Python3 mã làm việc trên. Tôi tin rằng đó là bởi vì mã hóa mặc định là utf-8)

+0

Tôi sẽ gọi một lỗi trong SQLAlchemy tbh, '__str__' phải trả về' str' và '__unicode__' sẽ trả về' unicode'. Bạn nên gửi vấn đề này như một vấn đề. Bạn có thể làm việc xung quanh nó bằng cách làm 'in (str (e) .decode (" utf-8 "))' ở khắp mọi nơi, đó là tẻ nhạt, nhưng không phải là điều tồi tệ nhất trên thế giới. – univerio

+0

Tôi sẽ giải quyết vấn đề này. Nhưng tôi không thể sửa chữa nó như được đề xuất, như các mã có liên quan là trong Flask-Admin. Tôi cần một giải pháp có phần toàn cầu hơn. – tmrlvi

+0

@tmrlvi Bạn có thể đăng ở đây liên kết tới vấn đề bạn đã gửi không? –

Trả lời

2

Tôi thực sự nghĩ rằng vá SQLAlchemy từ ứng dụng của bạn là đúng sự hợp lý sạch dung dịch. Dưới đây là lý do:

  • Bạn đã xác định được điều gì đó thường được đồng ý là lỗi trong SQLAlchemy.

  • Bạn có thể viết một bản vá sẽ hoạt động giống nhau cho tất cả các tình huống mà SQLAlchemy hiện đang làm việc. Tức là, bản vá của bạn sẽ không phá vỡ mã hiện tại

  • Xác suất là rất cao ngay cả khi SQLAlchemy được sửa vá của bạn sẽ vô hại.

  • Thực hiện thay đổi này làm giảm tác động của lỗi SQLAlchemy trong suốt mã của bạn qua các giải pháp như thay đổi mọi nơi ngoại lệ có thể được in.

  • Thay đổi PostGres để trả về mã hóa latin1 thực sự sẽ không giúp ích bởi vì python đang sử dụng mã hóa ascii, sẽ cung cấp cùng lỗi khi đưa ra chuỗi latin1. Ngoài ra, việc thay đổi PostGres để trả về các lỗi latin1 có thể sẽ liên quan đến việc thay đổi mã hóa kết nối; có khả năng tạo ra các vấn đề cho dữ liệu unicode.

Đây là chương trình đơn giản vá lỗi sqlalchemy.exc.StatementError và kiểm tra bản vá. Nếu bạn muốn bạn thậm chí có thể thử tạo ra một ngoại lệ bao gồm unicode, chuyển đổi thành unicode, và chỉ áp dụng các bản vá nếu điều đó làm tăng UnicodeDecodeError. Nếu bạn đã làm điều đó, bản vá của bạn sẽ tự động ngừng được áp dụng khi sqlalchemy khắc phục vấn đề.

# -*- coding: utf-8 -*- 
from sqlalchemy.exc import StatementError 

def statement_error_unicode(self): 
    return unicode(str(self), 'utf-8') 
# See <link to sqlalchemy issue>; can be removed once we require a 
# version of sqlalchemy with a fix to that issue 
StatementError.__unicode__ = statement_error_unicode 

message = u'Sqlalchemy unicode ' 
message_str = message.encode('utf-8') 
error = StatementError(message_str, 'select * from users', tuple(), '') 
print unicode(error) 
Các vấn đề liên quan