自定義類別支援 range-based for loop 寫法

本篇 ShengYu 介紹如何讓自定義類別支援 range-based for loop 的寫法。

range-based for loop 是 C++11 中增加的新特性,使用 range-based for loop 避免了存取越界,也提高了程式的可讀性以及寫程式的效率。range-based for loop 的寫法如下,先來複習一下,

1
2
3
4
vector<int> vec = {1, 2, 3};
for (auto& v : vec) {
cout << v << endl;
}

要讓自己寫的 class 支援 range-based for loop 關鍵在於實作 begin()end(),如下範例所示,如果自己寫的 class 沒有實作 begin()end() 的話會出現 error: invalid range expression of type 'MyList'; no viable 'begin' function available 的編譯錯誤訊息,以下範例以自定義的 MyList 與 std::list 為例,MyList 內部還是使用 std::list 當作主要的存取容器,這邊就要來寫 begin()end() 的實作來支援 range-based for loop 的寫法,

cpp-myclass-range-based-for-loop.cpp
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
// g++ cpp-myclass-range-based-for-loop.cpp -o a.out -std=c++11
#include <iostream>
#include <list>
using namespace std;

class MyList {
public:
MyList() {}

void push_back(int n) { mList.push_back(n); }

list<int>::iterator begin() { return mList.begin(); }
list<int>::iterator end() { return mList.end(); }
list<int>::const_iterator begin() const { return mList.cbegin(); }
list<int>::const_iterator end() const { return mList.cend(); }
// or
//auto begin() { return mList.begin(); } // need C++14
//auto end() { return mList.end(); } // need C++14
//auto begin() const { return mList.begin(); } // need C++14
//auto end() const { return mList.end(); } // need C++14
private:
list<int> mList;
};

int main() {
list<int> list1;
list1.push_back(1);
list1.push_back(2);
list1.push_back(3);
for (auto& l : list1) {
cout << l << endl;
}

MyList list2;
list2.push_back(4);
list2.push_back(5);
list2.push_back(6);
for (auto& l : list2) {
cout << l << endl;
}

return 0;
}

輸出如下,這樣 MyList 跟原本的 list 容器一樣都能提供 支援 range-based for loop 的寫法了,

1
2
3
4
5
6
1
2
3
4
5
6

其他參考
c++ - How to allow range-for loop on my class? - Stack Overflow
https://stackoverflow.com/questions/18321092/how-to-allow-range-for-loop-on-my-class
[c++]自定义class的for each loop_I have a adream-CSDN博客
https://blog.csdn.net/adream307/article/details/86721033
AOSP 的 service_list class
https://github.com/aosp-mirror/platform_system_core/blob/34a0e57a257f0081c672c9be0e87230762e677ca/init/service_list.h
service_list 使用 range-based for loop 的範例在 service_utils.cpp 裡
https://github.com/aosp-mirror/platform_system_core/blob/34a0e57a257f0081c672c9be0e87230762e677ca/init/test_utils/service_utils.cpp

Python Flask 螢幕分享

本篇 ShengYu 要介紹使用 Python Flask 螢幕分享的作法,完成後就可以將你的桌面螢幕利用網頁的方式串流影像出去,其它使用者只需要一個瀏覽器就可以看你的螢幕分享(電腦或手機或平板)。

在之前的文章中曾經介紹過 Python Flask 的網頁開發攝影機串流以及螢幕截圖,今天來點不一樣的,來作個螢幕分享的功能吧!

本篇所使用到的 Python 模組有

  • Flask
  • pyscreenshot (Linux)
  • PIL ImageGrab (Windows and macOS)

顯示圖片的 Flask 網頁

基於之前的 Flask 系列文章介紹,可以透過下列的程式碼簡單的建立一個網頁並顯示一張圖片,

index.html
1
2
3
4
5
6
7
<html>
<head>
</head>
<body>
<img src="{{ url_for('video_feed') }}" alt="" style="width: 100%">
</body>
</html>

之前介紹過 Flask 使用 template 的方式了,這邊就直接使用吧!

main.py
1
2
3
4
5
6
7
8
9
10
import flask

app = flask.Flask(__name__)

@app.route('/')
def index():
return flask.render_template('index.html')

if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)

但是這次我不只單純顯示一張圖片就好,我要顯示一連串圖片,

Flask 顯示串流影像

攝影機串流這篇介紹到可以將一張張影像串流出去,

boundary=--jpgboundary
指出後續的連續資料塊以 --jpgboundary 作為各單位資料區塊邊界
你也可以改用
boundary=frame
之後連續資料塊以 --frame 作為各單位資料區塊邊界

這邊我在 Ubuntu 系統下使用 pyscreenshot 來擷取螢幕的畫面,Windows 與 macOS 系統直接使用 PIL ImageGrab 即可

轉 bytes 方式有兩種,一種是先 seek(0) 再 read() 可以讀取 bytes 資料

1
2
3
4
img_buffer = BytesIO()
ImageGrab.grab().save(img_buffer, 'JPEG')
img_buffer.seek(0)
img_buffer.read() # bytes

另一種是直接 getvalue(),就不用 seek

1
2
3
img_buffer = BytesIO()
ImageGrab.grab().save(img_buffer, 'JPEG')
img_buffer.getvalue() # bytes

Ubuntu 遇到 IMageGrab 錯誤訊息的解決方法

在 Ubuntu 下執行時如果遇到 ImageGrab is macOS and Windows only 的錯誤訊息時,代表 ImageGrab 這個模組只支援 OS X 跟 Windows,

在 Linux 平台下可以用 pyscreenshot 模組來取代 ImageGrab,
把原本的

1
from PIL  import ImageGrab

替換成

1
import pyscreenshot as ImageGrab

這樣就可以了。

以上的完整原始碼放在我的 github 上。

其它參考
https://stackoverflow.com/questions/43520757/imagegrab-alternative-in-linux

其它相關文章推薦
Python Flask & OpenCV 即時串流 webcam 攝影機影像

Python 螢幕截圖存檔 pyscreenshot 用法

本篇 ShengYu 要介紹如何使用 Python pyscreenshot 螢幕截圖存檔,pyscreenshot 是 PIL ImageGrab 模組在 Linux 下的替代方案,PIL 的 ImageGrab 只支援 Windows 與 macOS,所以在 Windows 與 macOS 系統下直接使用 PIL ImageGrab 模組就可以了,同樣的程式碼如果要在 Linux 下使用的話,只需要裝 pyscreenshot 這個模組即可馬上使用。

安裝 pyscreenshot 模組

1
$ pip3 install Pillow pyscreenshot

螢幕截圖輸出成 jpeg

python3-pyscreenshot-jpeg.py
1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab()
img.save('fullscreen.jpeg', quality=70)

螢幕截圖輸出成 jpeg 並加上當下系統時間

python3-pyscreenshot-jpeg-with-time.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab
import time

img = ImageGrab.grab()
filename = 'fullscreen-' + time.strftime('%Y-%m-%d_%H-%M-%S') + '.jpeg'
img.save(filename, quality=70)

生成的檔案名稱就會是 fullscreen-2021-06-14_21-22-40.jpeg 這樣的格式。

螢幕截圖輸出成 png

python3-pyscreenshot-png.py
1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab()
img.save('fullscreen.png', quality=80)

螢幕截圖輸出成 bmp

python3-pyscreenshot-bmp.py
1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab()
img.save('fullscreen.bmp')

螢幕截圖輸出成 BytesIO

以下示範 jpeg 影像格式,也可用 png 或其它,

python3-pyscreenshot-bytesio.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab
from io import BytesIO

img_buffer = BytesIO()
img = ImageGrab.grab()
img.save(img_buffer, 'JPEG', quality=80)

螢幕截圖並顯示

python3-pyscreenshot-show.py
1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab()
img.show()

指定範圍的螢幕截圖

以下示範指定範圍 (10,10)左上 - (510,510) 右下的 500x500 螢幕截圖,

python3-pyscreenshot-grabbox.py
1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab(bbox=(10, 10, 510, 510)) # X1, Y1, X2, Y2
img.show()

強制指定 backend

grab() 預設會去嘗試每一種 backend,grab() 傳入指定 backend,這邊以 mss 為例,,如果很確定要使用哪種 backend 的話可以直接指定,避免無效的嘗試。

python3-pyscreenshot-mss-backend.py
1
2
3
4
5
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab(backend='mss')

查詢 backend

使用 backends() 可以印出目前支援的 backends 後端,但不代表該後端就可以使用,例如 scrot 後端就要先安裝 scrot 這個指令才可以使用。

1
2
3
4
5
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

print(ImageGrab.backends())

以我的 Ubuntu 16.04 為例,輸出的結果如下,

1
2
backends ['pyside2', 'mac_screencapture', 'wx', 'pyqt', 'maim', 'grim', 'gnome_dbus', 'kwin_dbus', 'gnome-screenshot', 'ima
gemagick', 'pyside', 'pil', 'scrot', 'mss', 'pyqt5', 'pygdk3', 'mac_quartz']

高效能截圖

設定 childprocess 為 False 可以獲得更好的效能,

1
2
3
4
5
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyscreenshot as ImageGrab

img = ImageGrab.grab(backend="mss", childprocess=False)

使用 pyscreenshot.check.versions 模組可以看各後端的版本號碼,以我的 Ubuntu 16.04 為例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ python3 -m pyscreenshot.check.versions
python 3.5.2
pyscreenshot 3.0
scrot
gnome-screenshot 3.18.0
mac_screencapture
pygdk3 3.20.0
pyqt5 5.5.1
pil 4.2.0
maim
wx
pyside2
pyqt
grim
mss 6.1.0
gnome_dbus ?.?
imagemagick 6.8.9
pyside
kwin_dbus ?.?
mac_quartz

使用 pyscreenshot.check.speedtest 模組可以測試各後端的效能,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ python3 -m pyscreenshot.check.speedtest

n=10
------------------------------------------------------
default 3.9 sec ( 385 ms per call)
mac_quartz
pyqt
imagemagick 2.4 sec ( 239 ms per call)
mac_screencapture
maim
pyside
grim
gnome-screenshot 2.3 sec ( 228 ms per call)
kwin_dbus
gnome_dbus
scrot
mss 2.5 sec ( 246 ms per call)
pygdk3 2.6 sec ( 263 ms per call)
wx
pyside2
pyqt5 4.8 sec ( 476 ms per call)
pil

使用 pyscreenshot.check.speedtest 模組並指定 –childprocess 0 測試各後端的效能,已我的系統來說 mss 效能最好,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ python3 -m pyscreenshot.check.speedtest --childprocess 0

n=10
------------------------------------------------------
default 0.15 sec ( 15 ms per call)
pyside2
pyqt
pyside
gnome-screenshot 2.3 sec ( 228 ms per call)
kwin_dbus
scrot
wx
pil
pygdk3 0.17 sec ( 17 ms per call)
gnome_dbus
imagemagick 2.5 sec ( 245 ms per call)
mac_screencapture
mac_quartz
maim
pyqt5 1.1 sec ( 114 ms per call)
mss 0.15 sec ( 15 ms per call)
grim

其它參考
GitHub - ponty/pyscreenshot: Python screenshot library, replacement for the Pillow ImageGrab module on Linux.
https://github.com/ponty/pyscreenshot/
pyscreenshot · PyPI
https://pypi.org/project/pyscreenshot/

4 種常用的縮短網址服務

短網址服務就是把冗長的網址變短,你之後只需要記住短網址即可,方便分享網址。

PPT.cc

https://ppt.cc/
台灣老牌的短網址服務

PPT.cc 的優點

  • 可以額外設定密碼

TinyUrl

https://tinyurl.com/app
全球歷史悠久的短網址服務

Bitly

https://bitly.com/
有名的短網址服務,在 Twitter 上很流行

Bitly 的優點

  • 免費註冊,註冊之後即可追蹤網址成效,在短網址後面輸入 + 即可看總點擊次數、QR Code、建立時間、分享到那些地方,來源國家
  • Chrome 瀏覽器擴充功能

Reurl

https://reurl.cc/
台灣的免費縮網址服務

在 macOS 發佈 Qt 程式

本篇 ShengYu 要介紹如何在 macOS 發佈 Qt 程式,如果你在 macOS 下開發的程式,想要到別人電腦裡可以正常執行起來的話,可以使用 qt 附帶的 macdeployqt 小工具,幫助你複製一些執行期間依賴的 qt 函式庫,

Qt macOS 發佈執行要用特殊小程式,輸出會是一個 dmg 檔案

1
~/Qt5.10.0/5.10.0/clang_64/bin/macdeployqt MyApp.app -dmg

或者不用 dmg 形式

1
~/Qt5.10.0/5.10.0/clang_64/bin/macdeployqt MyApp.app

其他參考
https://doc.qt.io/qt-5/macos-deployment.html

Android MJPEG Streaming App

今天要挑戰活化舊 Android 手機,充當 ip cam,當作寶寶監視器,以下為我的摸索過程,
一開始我找到的是 https://github.com/Teaonly/android-eye 這專案,把它編譯起來費了好大功夫,
還要編譯 x264,總之搞定後實測效果不好,
影像延遲很嚴重,慢了2-3秒,但我家 WiFi 是 5G,我並不覺得會慢到這樣。

後來想到之前寫過攝影機影像即時串流 MJPEG streaming 的 side project,便想找找看有沒有 MJPEG (Motion JPEG) streaming 的 Android App 開源專案,最後被我找到一個效果不錯的,是使用 MJPEG streaming 的 Android App
https://github.com/arktronic/cameraserve

後來便稍微研究一下如何在 Android 裡拿到 Camera 影像,以及轉換成 Jpeg 的程式碼流程,
實作 Camera.onPreviewFrame() Callback 並且註冊,之後將會得到預覽前的 frame,可以在這邊作你想要的處理,
關於 preview callback 這篇也講解的不錯,
在這個專案裡它是在 onPreviewFrame 裡將 YuvImage 影像直接轉成 Jpeg,

臨時要看 AOSP 原始碼可以使用 http://androidxref.com/ 網頁來看 Android 的原始碼,好處是它可以點擊函式名稱就可以跳至定義處,

YuvImage.java 裡面的 compressToJpeg 最後會呼叫 nativeCompressToJpeg
nativeCompressToJpeg的原始碼位置在 frameworks/base/core/jni/android/graphics/YuvToJpegEncoder.cpp

在網路上找專案用 android studio 開啟時時常用到 android gradle 版本批配問題,這邊列出官方的對應表

1
2
3
插件版本	所需的 Gradle 版本
4.1.0+ 6.5+
4.2.0+ 6.7.1+

其它參考
Android 系统Api YuvImage.compressToJpeg 存在native级别的内存泄漏_ChineseBoy_LY的博客-CSDN博客
https://blog.csdn.net/q979713444/article/details/80446404

其它相關文章推薦
Python Flask OpenCV 攝影機影像即時串流

Python Queue 用法與範例

本篇 ShengYu 將介紹如何使用 Python Queue 用法與範例,Python Queue 是實作 multi-producer multi-consumer queue,適用於多執行緒中的資訊交換。Queue 在 Python 2 和 Python 3 的 import 不一樣,Python 2 是 import Queue,Python 3 是 import queue,本篇以 Python 3 為主,Python 提供了三種 Queue,分別為

  • queue.Queue:FIFO 先進先出
  • queue.LifoQueue:LIFO類似於堆疊 stack,即先進後出
  • queue.PriorityQueue:優先級別越低越先出來

本篇介紹基本的 Queue 先進先出。

Queue 的常用的成員函式有以下,
Queue.qsize():返回 Queue 的大小
Queue.empty():如果 Queue 為空,返回 True,反之返回 False
Queue.full():如果 Queue 滿了,返回 True,反之返回 False
Queue.get([block[, timeout]]):取出 Queue,timeout 可以指定等待時間
Queue.get_nowait():等於 Queue.get(False)
Queue.put(item):放入 Queue,timeout 可以指定等待時間
Queue.put_nowait(item):等於 Queue.put(item, False)
Queue.task_done():在完成一項工作之後,Queue.task_done() 向任務已經完成的 Queue 發送一個訊號
Queue.join():等待直到 Queue 為空,再繼續執行

Queue 的放入與取出

Queue 放入是使用 put(),取出是 get(),以下面的例子來說,放出 3 個元素後,再取出 3 個元素,這時 Queue 裡面是空的狀態。

python3-queue.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import queue

q = queue.Queue()

q.put(1)
q.put(2)
q.put(3)

print(q.empty())
print(q.get())
print(q.get())
print(q.get())
print(q.empty())

輸出如下,

1
2
3
4
5
False
1
2
3
True

Queue 放入各種變數類型

Queue 可以放入各種變數類型,整數、浮點數、字串或其它類型。

python3-queue2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from queue import Queue

q = Queue()

q.put('hello')
q.put('world')
q.put(123)

print(q.get())
print(q.get())
print(q.get())

輸出如下,

1
2
3
hello
world
123

設定 Queue 的 maxsize

在 Queue 初始化時可以傳入 maxsize 來設定 Queue 的上限,以下示範設定 Queue 上限為 3。

python3-queue3.py
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from queue import Queue

q = Queue(maxsize=3)

for i in range(5):
q.put(i)
print('put ' + str(i))

while not q.empty():
print(q.get())

輸出如下,發現在第 4 次 put 時卡住,

1
2
3
put 0
put 1
put 2

原因是因為我們限制 maxsize 為 3,滿了之後要 put 會 block 卡住,
改成 q.put(i, block=False) 的話就不會 block 但要自行 ,因為內部會 raise Full,這邊就不示範了。另外使用 q.put(block=False)q.put_nowait()q.get() 也有對應的 q.get_nowait()

Queue 達到上限時可以針對當下需求作變化,有些情況是用丟棄舊元素保留最新元素,作法就是判斷 Queue 滿了就取出一些舊元素,

1
2
3
while queue.qsize() > 3:
queue.get(block=False)
queue.put(i)

有些情況則是用丟棄最新元素包留舊元素,作法就是判斷 Queue 沒滿才放入新元素,

1
2
if queue.qsize() < 3:
queue.put(i)

在多執行緒裡使用 Queue

在設計模式(design pattern)中,這是一個典型的生產者與消費者(producer-consumer)的例子,
範例裡有一位生產者 producer 每 2 秒生產了 1 個東西放到 Queue 裡,當 Queue 達到上限 10 的話 producer 就跳過這次不放東西進 Queue 裡,Queue 達到上限滿了要跳過不放入還是 block 等待直到 Queue 有空位,完全取決於當下的情況作設計,這邊只作簡單的示範,

另外有一位消費者 consumer 的會每隔1秒來取貨作後續的事情,當 Queue 空的話就跳過這次不取出東西。

Python 的 Queue 是 thread safe,Queue 的內部已經有實作 Condition 與 Lock 保護臨界區,所以在多執行緒中使用 Queue 可以不用自己上鎖。

python3-queue4.py
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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import queue
import time
import random
import threading

q = queue.Queue(10)

class Producer(threading.Thread):
def __init__(self, thread_name):
super(Producer, self).__init__(name=thread_name)

def run(self):
global q
count = 1
while True:
if q.full():
print('queue is full')
pass
else:
msg = str(count)
q.put(msg)
print(self.name + ' put ' + msg + ', qsize: ' + str(q.qsize()))
count=count+1
time.sleep(2)
#time.sleep(random.random())

class Consumer(threading.Thread):
def __init__(self, thread_name):
super(Consumer, self).__init__(name=thread_name)

def run(self):
global q
while True:
if q.empty():
print('queue is empty')
pass
else:
msg=q.get()
print(self.name + ' get ' + msg + ', qsize: ' + str(q.qsize()))
time.sleep(1)

p = Producer('producer')
p.start()

c = Consumer('consumer')
c.start()

輸出如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
producer put 1, qsize: 1
consumer get 1, qsize: 0
queue is empty
queue is empty
producer put 2, qsize: 1
consumer get 2, qsize: 0
producer put 3, qsize: 1
consumer get 3, qsize: 0
queue is empty
producer put 4, qsize: 1
consumer get 4, qsize: 0
queue is empty
producer put 5, qsize: 1
consumer get 5, qsize: 0
queue is empty
producer put 6, qsize: 1
consumer get 6, qsize: 0

以上就是 Python Queue 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它參考
queue — A synchronized queue class — Python 3 documentation
https://docs.python.org/3.7/library/queue.html

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包

Python QR Code 轉文字

本篇 ShengYu 介紹 Python QR Code 轉文字的方法。

這邊我們要使用 opencv 來將 QR Code 轉文字,先安裝好 Python 的 opencv 套件,

1
pip3 install opencv

安裝好 Python 的 opencv 套件之後,將 hello world 這個字串轉成 QR Code 看看,可以透過之前的文字轉 QR Code 教學產生出 hello world 的 QR Code 圖檔來當輸入檔案,

python3-qrcode-decode.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2

img = cv2.imread('qrcode.png')
qr_detector = cv2.QRCodeDetector()
retval, points, straight_qrcode = qr_detector.detectAndDecode(img)
print('text=' + retval)

程式輸出結果如下,

1
text=hello world

QR Code 轉文字小工具

我將上述這功能整理成一個小工具,變成執行程式時帶入任意 QR Code 檔名,便能將該 QR Code 轉換成字串並輸出,

python3-qrcode2text.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import cv2

if __name__ == '__main__':
if len(sys.argv) < 2:
print('no argument')
sys.exit()
fname = sys.argv[1]
img = cv2.imread(fname)
qr_detector = cv2.QRCodeDetector()
retval, points, straight_qrcode = qr_detector.detectAndDecode(img)
print('text=' + retval)

以上就是本篇的 Python QR Code 轉文字教學。

其它相關文章:Python 文字轉 QR Code

Python 文字轉 QR Code

本篇 ShengYu 介紹 Python 文字轉 QR Code 的方法。

最基本最簡單產生 QR Code 的方式如下,先安裝好 Python 的 qrcode 套件,

1
pip3 install qrcode

安裝好 Python 的 qrcode 套件後,將 hello world 這個字串轉成 QR Code 看看,程式碼如下,

python3-qrcode.py
1
2
3
4
5
6
7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import qrcode

img = qrcode.make('hello world')
img.save("qrcode.png")
img.show()

hello world 這個字串轉成的 QR Code 圖片如下所示,用任意的 QR Code 掃描 App 應該都可以掃描的出來這段文字,

文字轉 QR Code 小工具

我將上述這功能整理成一個小工具,變成執行程式時帶入任意字串,便能將該字串轉換成 QR Code 圖檔並顯示跟存檔,

python3-text2qrcode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import qrcode

if __name__ == '__main__':
if len(sys.argv) < 2:
print('no argument')
sys.exit()
s = sys.argv[1]
img = qrcode.make(s)
print('convert ' + s + ' to qrcode')
img.show()
print('save qrcode to qrcode.png')
img.save("qrcode.png")

以上就是本篇的 Python 文字轉 QR Code 教學。

其它相關文章:Python QR Code 轉文字

Excel 排序1位數、2位數、3位數、4位數

本篇 ShengYu 介紹 Excel 排序1位數、2位數、3位數、4位數,
原始資料如下,

1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
10
20
30
100
200
300
1000
2000
3000

有時排序後會產生這樣的結果,

1
2
3
4
5
6
7
8
9
10
11
12
1
10
100
1000
2
20
200
2000
3
30
300
3000

雖然這也是排序啦!但是我想要的結果是將1位數、2位數、3位數、4位數全部按大小排序,
選取儲存格的數字並且複製(ctrl+c),在新的欄位上滑鼠右鍵選擇「選擇性貼上」,
在運算選擇 ,然後按下確定,
再將新的欄位點擊排序就可以看到效果了。

其它參考
excel表格中的數字有一位數、兩位數、三位數,可是排序只按第一位數排,怎樣才能按1到10000的自然順序排呢_百度知道
https://zhidao.baidu.com/question/427424733.html