-
Notifications
You must be signed in to change notification settings - Fork 1
/
py3utf8.html
151 lines (141 loc) · 11.2 KB
/
py3utf8.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<!DOCTYPE html>
<html lang="vi">
<head>
<title>Tin tức Python PyMI.vn</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="utf-8" />
<link href="https://n.pymi.vn/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Tin tức Python PyMI.vn Full Atom Feed" />
<!-- twitter card metadata -->
<meta name="twitter:site" content="">
<meta name="twitter:title" content="Python3 str là unicode và rắc rối với utf-8">
<meta name="twitter:description" content="Một trường hợp print cho kết quả khác nhau giữa python2 và python3">
<!-- OG Tags -->
<meta property="og:url" content="./py3utf8.html"/>
<meta property="og:title" content="Python3 str là unicode và rắc rối với utf-8 | Tin tức Python PyMI.vn" />
<meta property="og:description" content="Một trường hợp print cho kết quả khác nhau giữa python2 và python3" />
<!-- favicon -->
<!-- moment.js for date formatting -->
<script src="./theme/js/moment.js"></script>
<!-- css -->
<link rel="stylesheet" type="text/css" href="./theme/css/main.css" />
<script>
/*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
(function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
grunticon(["./theme/css/icons.data.svg.css", "./theme/css/icons.data.png.css", "./theme/css/icons.fallback.css"]);
</script>
<noscript><link href="./theme/css/icons.fallback.css" rel="stylesheet"></noscript>
<!-- menu toggle javascript -->
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", initMenu);
function initMenu(){
var menu = document.getElementById("menu");
var menulink = document.getElementById("menu-link");
menulink.addEventListener("click", function toggleMenu(){
window.event.preventDefault();
menulink.classList.toggle('active');
menu.classList.toggle('active');
});
};
</script>
<meta name="description" content="Một trường hợp print cho kết quả khác nhau giữa python2 và python3" />
<meta name="tags" content="Unicode" />
<meta name="tags" content="UTF-8" />
<meta name="tags" content="python3" />
<meta name="tags" content="str" />
<meta name="tags" content="byte" />
<meta name="tags" content="hack" />
<meta name="tags" content="hex" />
</head>
<body>
<div role="banner" id="masthead">
<header>
<h1><a href="/">Pymiers's Blog</a></h1>
<a href="#menu" id="menu-link">more stuff</a>
<nav id="menu">
<ul>
<li><a href="./category/features.html">features</a></li>
<li class="active"><a href="./category/news.html">news</a></li>
<li><a href="./category/pymivn.html">pymi.vn</a></li>
</ul>
</nav>
</header>
</div>
<div class="page" role="main">
<div class="article" role="article">
<article>
<footer>
<a name="top"></a>
<p>
<time datetime=" 2022-07-25 21:35:00+07:00">
<script>document.write(moment('2022-07-25 21:35:00+07:00').format('LL'));</script>
</time>
</p>
</footer>
<header>
<h2>
Python3 str là unicode và rắc rối với utf-8
</h2>
<center>
<h4>
by Pymier0
</h4>
</center>
</header>
<div class="content">
<p>Python3 chỉ có 1 kiểu string là <code>str</code>.
Python2 có 2 kiểu string: <code>str</code> và <code>unicode</code></p>
<p>Sự hợp nhất này chính là <a href="https://docs.python.org/3/howto/unicode.html">ưu điểm rất lớn của Python3</a>, lập trình viên không phải đau đầu khi chuyển đổi giữa 2 kiểu string.</p>
<p>Python3 mặc định sử dụng <span class="caps">UTF</span>-8, với các giá trị <span class="caps">ASCII</span> < 128 (bảng chữ cái tiếng Anh, các số, các dấu) được giữ nguyên kích thước là 1 byte.</p>
<ul>
<li>If the code point is < 128, it’s represented by the corresponding byte value.</li>
<li>If the code point is >= 128, it’s turned into a sequence of two, three, or four bytes, where each byte of the sequence is between 128 and 255.</li>
</ul>
<p>Cho nên khi viết Python2: print “PyMiEr2022” và Python3 print(“PyMiEr2022”) cho kết quả như nhau.</p>
<p>Vì một số giá trị char < 128 không phải “ký tự” bình thường, có thể dùng dạng hex để viết nó, ví dụ print “\x13\x37” hay python3 print(“\x13\x37”) cho kêt quả như nhau.</p>
<p>Nhưng khi viết: python2 <code>print "\xaa"</code> so với Python3 <code>print("\xaa")</code> kết quả lại <strong>khác nhau</strong>:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span> <span class="n">python2</span> <span class="o">-</span><span class="n">c</span> <span class="s1">'print "</span><span class="se">\xaa</span><span class="s1">"'</span>
<span class="err">�</span>
<span class="err">$</span> <span class="n">python3</span> <span class="o">-</span><span class="n">c</span> <span class="s1">'print("</span><span class="se">\xaa</span><span class="s1">")'</span>
<span class="n">ª</span>
</code></pre></div>
<p>Sử dụng lệnh <code>hexdump</code> để nhìn output ở dạng hex:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span> <span class="n">python2</span> <span class="o">-</span><span class="n">c</span> <span class="s1">'print "</span><span class="se">\xaa</span><span class="s1">"'</span> <span class="o">|</span> <span class="n">hexdump</span>
<span class="mi">0000000</span> <span class="mi">0</span><span class="n">aaa</span>
<span class="mi">0000002</span>
<span class="err">$</span> <span class="n">python3</span> <span class="o">-</span><span class="n">c</span> <span class="s1">'print("</span><span class="se">\xaa</span><span class="s1">")'</span> <span class="o">|</span> <span class="n">hexdump</span>
<span class="mi">0000000</span> <span class="n">aac2</span> <span class="mi">000</span><span class="n">a</span>
<span class="mi">0000003</span>
</code></pre></div>
<p>Python2 tạo ra 2 bytes: <code>0a</code> (newline xuống dòng) và <code>aa</code>,
còn Python3 tạo ra tới 3 bytes, trong đó <code>aa</code> trở thành <code>aac2</code>. Tại sao?</p>
<p><img alt="img" src="https://images.unsplash.com/photo-1568884149074-a93f17583719?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwyMzI1MzN8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NTg3NTQxNzY&ixlib=rb-1.2.1&q=80&w=600"></p>
<p>Lý do bởi 0xaa có giá trị 170 > 128, trên Python3 sẽ được biểu diễn bằng 2 bytes, với aa là giá trị, còn c2 là ký tự “control” để thêm vào cho đủ 2 bytes.</p>
<p>Để in ra kết quả tương tự Python2, dùng:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">b</span><span class="s2">"</span><span class="se">\xaa</span><span class="s2">"</span><span class="p">)</span>
</code></pre></div>
<h2>Tham khảo</h2>
<ul>
<li><a href="https://discuss.python.org/t/unusal-behavior-of-python3-print-hex-values/15418/9">https://discuss.python.org/t/unusal-behavior-of-python3-print-hex-values/15418/9</a></li>
<li><a href="https://docs.python.org/3/howto/unicode.html">https://docs.python.org/3/howto/unicode.html</a></li>
<li><a href="https://stackoverflow.com/questions/908331/how-to-write-binary-data-to-stdout-in-python-3">https://stackoverflow.com/questions/908331/how-to-write-binary-data-to-stdout-in-python-3</a></li>
</ul>
<p>Hết.</p>
<p>Đăng ký ngay tại <a href="https://pymi.vn">PyMI.vn</a> để học Python tại Hà Nội <span class="caps">TP</span> <span class="caps">HCM</span> (Sài Gòn),
trở thành lập trình viên #python chuyên nghiệp ngay sau khóa học.</p>
</div>
<div class="back-to-top">
<a href="#top">back to top</a>
</div>
</article>
</div>
<!-- end article -->
<footer>
<div class="icons">
<a href="https://github.com/pymivn" target="_blank"><div class="icon-github icon"></div></a>
</div>
<p>© <script>document.write(moment().format('YYYY'));</script> Pymiers</p>
</footer>
</div>
</body>
</html>