2012-03-30 28 views
11

Tôi đang chuyển đổi 2 MB dữ liệu như là một chuỗi thành một dict. Đầu vào được đăng trong JSON.trăn eval vs ast.literal_eval vs JSON giải mã

Dù sao tôi hiện đang sử dụng ast.literal_eval và tôi lấy từ điển mình muốn, nhưng sau đó khi tôi thử chạy eval nó có vẻ chạy nhanh hơn, và cũng trả về cùng một kết quả.

Có lý do nào để sử dụng mô đun ast hoặc mô đun json khi eval hoạt động tốt không?

+0

Nếu bạn muốn phân phối từ điển cùng với mã của bạn, bạn có thể laso chỉ cần đặt nó trong một mô-đun Python và import nó. Bằng cách đó, bạn làm rõ ràng đây là mã Python. –

Trả lời

17

Có, có chắc chắn là một lý do: eval() là ác. Mã của bạn có thể đọc dữ liệu không tin cậy một ngày, điều này sẽ cho phép kẻ tấn công chạy mã tùy ý trên máy của bạn.

Bạn không nên sử dụng để giải mã ast.literal_eval() JSON một trong hai. Nó không thể giải mã mọi chuỗi JSON hợp lệ và không có nghĩa là được sử dụng cho mục đích này. Đơn giản chỉ cần sử dụng json.loads(), nó khá nhanh.

+1

Nếu họ chỉ có thể chạy trên máy của họ thì sao? (ví dụ: họ tải xuống và chạy nó) – MxyL

+2

@Keikoku: Vì vậy, nếu nó không phải là máy của bạn, bạn không quan tâm? –

+0

Tôi đoán họ có thể lan truyền nó xung quanh và làm những điều không rõ ràng với nó và tín dụng tôi cho công việc. – MxyL

4

eval là dễ bị mối đe dọa an ninh. Chỉ sử dụng khi bạn hoàn toàn kiểm soát những gì được eval'ed

+0

. globals? –

16

số Trừ khi bạn nhấn một trong hai kịch bản:

  1. Đó không phải là JSON!

    Một người nào đó đặt __import__('os').system('rm -rf /') vào tệp thay thế. Bạn đang boned.

  2. Đó là JSON, nhưng không phải là một phần Python-như thế!

    Ai đó đặt true, false, null hoặc thoát Unicode ở đâu đó trong đó. Chúc mừng sinh nhật.

+0

Làm thế nào về 'eval (json_str, {'false': Sai, 'true': True, 'null': None, '__builtins__': {}})'? ;-) –

+3

@NasBanov: xem http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html –

+0

@JanusTroelsen, vâng - xem http://stackoverflow.com/questions/7282905/does-converting-json-to này -dict-with-eval-a-good-choice/7282959 # comment14167166_7282959 - dường như có liên quan theo thời gian quá –

16

tôi không thực sự thích thái độ này trên stackoverflow (và các nơi khác) nói với mọi người mà không cần bất kỳ bối cảnh đó những gì họ đang làm là không an toàn và họ không nên làm điều đó. Có lẽ nó chỉ là một kịch bản throwaway để nhập một số dữ liệu, trong trường hợp đó tại sao không chọn cách nhanh nhất hoặc thuận tiện nhất?

Trong trường hợp này, tuy nhiên, json.loads không chỉ an toàn hơn mà còn nhanh hơn 4 lần (tùy thuộc vào dữ liệu của bạn).

In [1]: %timeit json.loads(data) 
10000 loops, best of 3: 41.6 µs per loop 

In [2]: %timeit eval(data) 
10000 loops, best of 3: 194 µs per loop 

In [3]: %timeit ast.literal_eval(data) 
1000 loops, best of 3: 269 µs per loop 

Nếu bạn nghĩ về nó có nghĩa là json là ngôn ngữ/định dạng hạn chế hơn python, vì vậy phải nhanh hơn để phân tích cú pháp với trình phân tích cú pháp được tối ưu hóa.

+0

SO là về nhiều hơn là trả lời câu hỏi của OP: nó trở thành một tham chiếu mà người khác cũng đọc. –

0

Không chính xác câu trả lời, nhưng cần lưu ý rằng evalliteral_eval không giống nhau. ast.literal_eval sẽ không chạy mã tùy ý.

Điều đó nói rằng, tôi đồng ý với việc sử dụng JSON; Tôi chỉ muốn chỉ ra rằng eval != literal_eval