Shell Script 讀檔,讀取 txt 文字檔

本篇要介紹如何在 shell script 腳本來讀取 txt 文字檔,讀檔且每次在 while 迴圈裡將讀取的文字印出來。

while 語法介紹與範例請看這篇

範例. 讀 text.txt 文字檔, 並且印出每一行

1
2
3
while read line ; do
echo "$line"
done < text.txt

範例. 將讀取的資料分離

使用 IFS (Internal Field Separator) ,資料會依據 IFS 所定義的區隔符號將一行資料中的資料儲存成不同變數.

1
2
3
4
while IFS=":" read -r f1 f2 f3 f4 f5 f6 f7;
do
echo "User:" $f1
done < /etc/passwd

下一篇介紹 sleep 延遲執行

其它相關文章推薦
Shell Script 新手入門教學
Shell Script 四則運算,變數相加、相減、相乘、相除
Shell Script if 條件判斷
Shell Script for 迴圈
Shell Script while 迴圈

Python 計算 str 字串長度

本篇 ShengYu 介紹 Python 計算 str 字串長度,Python 計算字串長度的用法與範例如下,

len() 可以用來計算 str 的長度,

1
2
s = 'hello world'
print(len(s))

輸出結果如下,

1
11

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python str 字串用法與範例
Python 計算 list 串列長度
Python 計算 dict 字典長度
Python 計算 tuple 元組長度
Python 計算 set 集合長度
Python 新手入門教學懶人包
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace
Python 產生 random 隨機不重複的數字 list
Python print 格式化輸出與排版
Python PIL 讀取圖片並顯示
Python OpenCV resize 圖片縮放

Python 建立簡單的 Tornado Web

本篇介紹用 Python 與 Tornado 來建立一個簡單的 Tornado Web,Tornado 相較於 Python 其他的主流 Web 框架的優勢就是速度快,Tornado 在效能上有的明顯地優勢,最先為 FriendFeed 公司的產品中使用,後來被 Facebook 收購後開源。

官方文件:http://www.tornadoweb.org/en/stable/
Github:https://github.com/tornadoweb/tornado
PyPI:https://pypi.org/project/tornado/

安裝 tornado

介紹如何在 Python 環境中安裝 tornado 模組,
執行程式時遇到 ImportError: No module named ‘tornado’ 這個錯誤訊息的話,請安裝 python 的 tornado 模組,

輸入下列指令安裝 pyserial 模組,以下列出 python 2 與 python 3 的方法︰
Python 2 安裝方法

1
$ sudo -H pip install tornado

Python 3 安裝方法

1
$ sudo -H pip3 install tornado

範例. Tornado Web 的 hello world

以下範例展示一個 Tornado 最簡單的 hello world 程式,將這程式執行起來後,
開啟 http://127.0.0.1:8080,即可看到網頁顯示 hello world 字樣,表示成功的完成這個範例。

這個範例一開始使用 make_app 函式來建立一個 tornado 的 application,
在 make_app 裡使用 tornado.web.Application 函式指定程式將 / URL 請求對應到 MainHandler,
這個 MainHandler class 主要是透過繼承 tornado.web.RequestHandler 來處理各種 Request 請求,
例如:get() 用來處理 HTTP GET 請求、post() 用來處理 HTTP POST 請求等等,
通常[ (r'/', MainHandler), ]這裡還可以指定更多種 URL 請求,但我們這邊只簡單介紹一個 URL 請求,

接著會使用 app.listen 來聆聽 port 8080 的 HTTP 請求,
所以只要有 http://127.0.0.1:8080/ 的 URL 請求,MainHandler 的 get 就會被呼叫來處理,
這邊的 get 裡我們簡單的回傳 Hello, world 字串,這個字串就是最終使用者會在瀏覽器上看到的字串,
接著使用 tornado.ioloop.IOLoop 開始進行主迴圈作事件等待,這樣一個簡單的 web 範例就完成了。

python-tornado-helloworld.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write('Hello, world')

def make_app():
return tornado.web.Application([
(r'/', MainHandler),
])

if __name__ == '__main__':
app = make_app()
app.listen(8080)
tornado.ioloop.IOLoop.current().start()

開啟瀏覽器的網頁瀏覽結果如下圖:

QA. 為什麼使用 Tornado?跟 Django 相比呢?

根據這篇網友的回答:
Django 常用於大型專案快速開發,且有SQL資料庫需求的專案。
Tornado 適用各種情形,例如:個人專案、WebSocket 相關、NoSQL backend 相關。

參考
Structure of a Tornado web application — Tornado documentation
https://www.tornadoweb.org/en/stable/guide/structure.html
Tornado web應用的結構 — Tornado 文檔
https://tornado-zh.readthedocs.io/zh/latest/guide/structure.html
分析 Hello - 《从零开始学 Python》(第二版) - 极客学院Wiki
https://wiki.jikexueyuan.com/project/start-learning-python/302.html
第二章:表单和模板 - Introduction to Tornado 中文翻译
https://mirrors.segmentfault.com/itt2zh/ch2.html

其它相關文章推薦
Python 快速建立簡單網頁伺服器 http websever
[Python小專案] Tornado+PyAutoGUI 多媒體控制播放的網頁
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace
Python 建立多執行緒 thread
Python OpenCV resize 圖片縮放
Python OpenCV 顯示camera攝影機串流影像

Python logging 日誌用法與範例

本篇將介紹 Python 內建的 logging 用法與範例,Python 的 logging 可以將 log 輸出到 console 與輸出到日誌檔裡,接下來就開始本篇的 Python logging 教學吧。

Python logging 的 log level 有五種等級,分別為DEBUG、INFO、WARNING、ERROR、CRITICAL,預設 log level 等級是 WARNING。
log level 等級與分別對應的 api 如下:
DEBUG:logging.debug()
INFO:logging.info()
WARNING:logging.warning()
ERROR:logging.error()
CRITICAL:logging.critical()

範例. 簡單的基本 logging

Python logging 基本用法與範例如下,預設的 log level 是 WARNING,代表大於或等於 WARNING 以上的 log 才會記錄(WARNING、ERROR、CRITICAL),不會記錄 DEBUG 與 INFO,

Python 的 logging 如果沒有設定 log filename 檔名的話就不會將日誌紀錄在檔案裡只會輸出顯示在 console 上,預設是沒有設定日誌檔名,

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

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')

輸出如下,可以發現logging.debug()logging.info()的訊息都沒有出現,

1
2
3
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical

根據上面的範例進行修改,
將 log level 修改成 DEBUG,讓 DEBUG level 與 INFO level 的 log 都顯示出來。

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

logging.basicConfig(level=logging.DEBUG)
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')

輸出:

1
2
3
4
5
DEBUG:root:debug
INFO:root:info
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical

範例. 進階的日誌使用方式

以下範例為實際上使用情形,使用 logging.basicConfig 來設定,設定時可以指定 log level 這樣 debug info 就可以顯示出來了,設定 log 的 filename 後只會輸出到檔案不會輸出在 console,
filemode='w'表示為覆寫模式,之前的檔案會被覆蓋過去,預設是添加模式,會將內容接在上次檔案的尾端繼續寫入,

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

logging.basicConfig(level=logging.INFO, filename='log.txt', filemode='w',
format='[%(asctime)s %(levelname)-8s] %(message)s',
datefmt='%Y%m%d %H:%M:%S',
)

if __name__ == "__main__":
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')

輸出log檔內容如下:

log.txt
1
2
3
4
[20200414 21:34:40 INFO    ] info
[20200414 21:34:40 WARNING ] warning
[20200414 21:34:40 ERROR ] error
[20200414 21:34:40 CRITICAL] critical

範例. 簡潔的日誌風格

這邊示範簡潔的日誌的格式,將 level 縮短變成一個字母,format 裡還能指定 module 名稱與程式碼行數,
你也可以將 log 的檔名依照日期時間來命名,

python-logging3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
import datetime

log_filename = datetime.datetime.now().strftime("%Y-%m-%d_%H_%M_%S.log")
logging.basicConfig(level=logging.INFO, filename=log_filename, filemode='w',
#format='[%(levelname).1s %(asctime)s] %(message)s',
format='[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s',
datefmt='%Y%m%d %H:%M:%S',
)

if __name__ == "__main__":
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')

輸出log檔內容如下:

2020-04-14_21_34_59.log
1
2
3
4
[I 20200414 21:34:40 python-logging3:14] info
[W 20200414 21:34:40 python-logging3:15] warning
[E 20200414 21:34:40 python-logging3:16] error
[C 20200414 21:34:40 python-logging3:17] critical

範例. 同時輸出到 console 與日誌檔

使用 logging 如果想要同時輸出到 console 與日誌檔只能手動加一些程式碼去設定,
在 Python logging 套件的 basicConfig() 裡的原始碼可以發現 console(StreamHandler) 與 日誌檔(FileHandler) 這兩種功能只能擇一使用,
手動加一些程式碼同時輸出到 console 與日誌檔的範例如下,
先使用 StreamHandler 輸出到console,
再使用 FileHandler 輸出到日誌檔,
最後在添加這兩個 Handler

python-logging4.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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
import datetime

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s',
datefmt='%Y%m%d %H:%M:%S')

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)

log_filename = datetime.datetime.now().strftime("%Y-%m-%d_%H_%M_%S.log")
fh = logging.FileHandler(log_filename)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)

logger.addHandler(ch)
logger.addHandler(fh)

if __name__ == "__main__":
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')

結果如先前一樣。

logging.basicConfig 常用參數

以下為 logging.basicConfig 常用的參數與說明,
level:顯示日誌的等級
filename:log 的檔名
format:log 的輸出格式
datefmt:輸出時間的格式
filemode:日誌開啟模式
handlers:與filename與stream不相容,無法同時使用
stream:與handlers不相容,無法同時使用
style:formatter 使用 % 還是 {} 還是 $

使用 logging.basicConfig 可以對 logging 進行設定外,也可以透過另一個 logging.fileConfig 的方式來對 logging 進行設定,logging.fileConfig 就是將 config 檔案裡的設定值讀取進來作設定,詳細使用請參考logging.config.fileConfig()Configuration file format

logging format 常用輸出格式

以下為 logging format 常用輸出格式與說明,
%(asctime)s:日期時間
%(filename)s:模組檔名
%(funcName)s:函式名稱
%(levelno)s:行數
%(levelname)s:logging level
%(levelno)s:logging level 的數值
%(message)s:訊息
%(module)s:模組名稱

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

參考
Python 3 官方教學
https://docs.python.org/3/library/logging.html
[Python] logging 教學 – Max的程式語言筆記
https://stackoverflow.max-everyday.com/2017/10/python-logging/
Python - 日誌 (logging) 模組 | Titangene Blog
https://titangene.github.io/article/python-logging.html
小狐狸事務所: Python 學習筆記 : 日誌 (logging) 模組測試
http://yhhuang1966.blogspot.com/2018/04/python-logging_24.html
tornado/log.py at master · tornadoweb/tornado
https://github.com/tornadoweb/tornado/blob/master/tornado/log.py
Python logging同时输出到屏幕和文件 - 孤鸿的天空
https://xnathan.com/2017/03/09/logging-output-to-screen-and-file/
Python logging浅尝(将log同时输出到Console和日志文件)_小桔的博客-CSDN博客
https://blog.csdn.net/u010895119/article/details/79470443

其它相關文章推薦
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace
Python 建立多執行緒 thread
Python OpenCV resize 圖片縮放
Python OpenCV 顯示camera攝影機串流影像
Python 快速建立簡單網頁伺服器 http websever
Python 建立簡單的 Tornado Web
[Python小專案] Tornado+PyAutoGUI 多媒體控制播放的網頁

std::atomic 用法與範例

本篇介紹 C++ 的 std::atomic 用法,並提供一些範例。

atomic用來保證原子操作,但不保證類型T是無鎖(lock_free)的,
因為不同平台的實作方式不同,可以用is_lock_free成員函式來判斷是不是無鎖的,
另外atomic_flag肯定是無鎖的。

以下循序漸進地介紹使用 atomic,以及為什麼用 atomic。

最簡單的直覺寫法,但是結果錯誤

以下範例為100個執行緒一起執行,並且同時將全域變數 cnt 取出來 +1 計數,
但是由於多個執行緒同時存取 cnt 的關係會造成資料不正確。
來看看結果輸出會是怎樣吧!

std-atomic.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
// g++ std-atomic.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>

using namespace std;

long cnt = 0;

void counter()
{
for (int i = 0; i < 100000; i++) {
cnt += 1;
}
}

int main(int argc, char* argv[])
{
auto t1 = std::chrono::high_resolution_clock::now();
std::thread threads[100];
for (int i = 0; i != 100; i++)
{
threads[i] = std::thread(counter);
}
for (auto &th : threads)
th.join();

auto t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = t2 - t1;
std::cout << "result: " << cnt << std::endl;
std::cout << "duration: " << elapsed.count() << " ms" << std::endl;
return 0;
}

輸出如下,

1
2
result: 1866806
duration: 61.7727 ms

結果答案不是我們所預期的 10000000,而且每次跑得結果都不一樣,那考慮加個 mutex 鎖試試看吧!

接著最直覺地加上了 mutex 鎖

加 mutex 鎖來保護臨界區域是最常見的做法,
使用 mutex 來確保同一時間內只有一個執行緒可以存取 cnt,如果對 mutex 不熟悉的話可以看之前的 mutex 介紹
這次來看看結果輸出會是怎樣吧!

std-atomic2.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
// g++ std-atomic2.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

long cnt = 0;
std::mutex mtx;

void counter()
{
for (int i = 0; i < 100000; i++) {
std::lock_guard<std::mutex> lock(mtx);
//std::cout << std::this_thread::get_id() << ": " << cnt << '\n';
//mtx.lock();
cnt += 1;
//mtx.unlock();
}
}

int main(int argc, char* argv[])
{
auto t1 = std::chrono::high_resolution_clock::now();
std::thread threads[100];
for (int i = 0; i != 100; i++)
{
threads[i] = std::thread(counter);
}
for (auto &th : threads)
th.join();

auto t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = t2 - t1;
std::cout << "result: " << cnt << std::endl;
std::cout << "duration: " << elapsed.count() << " ms" << std::endl;
return 0;
}

輸出如下,

1
2
result: 10000000
duration: 1426.77 ms

這次答案正確了,以我的電腦所花的時間是 1426.77 ms,這個時間會因電腦規格不同而有所不同,
正確地使用 mutex 可以保證資料的正確性,但同時犧牲了效能,
那接下來我們會好奇想要知道,有沒有時間更快的方式呢?atomic?

使用 atomic 達到同樣效果,時間約少了7倍,效能大爆發

接下來這裡介紹本篇重頭戲 atomic,
如果對象是 long 的話,可以用 std::atomic<long>,也可以用 std::atomic_long這個類別,
用 atomic 也可以達到同樣的效果,但所花費的時間有減少嗎?
來看看結果輸出會是怎樣吧!

std-atomic3.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
// g++ std-atomic3.cpp -o a.out -std=c++11 -pthread
#include <iostream>
#include <thread>
#include <atomic>

using namespace std;

//std::atomic<long> cnt(0);
std::atomic_long cnt(0);

void counter()
{
for (int i = 0; i < 100000; i++) {
cnt += 1;
}
}

int main(int argc, char* argv[])
{
auto t1 = std::chrono::high_resolution_clock::now();
std::thread threads[100];
for (int i = 0; i != 100; i++)
{
threads[i] = std::thread(counter);
}
for (auto &th : threads)
th.join();

auto t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = t2 - t1;
std::cout << "result: " << cnt << std::endl;
std::cout << "duration: " << elapsed.count() << " ms" << std::endl;
return 0;
}

輸出如下,

1
2
result: 10000000
duration: 225.587 ms

這次使用 atomic 的答案也是正確的,同時地只花費了 225.587 ms,相對於 mutex 版本時間花費大幅減少了!
性能簡直大爆發了!!
透過這篇的學習,我們已經認識了 atomic 的威力,接下來的章節介紹更多的 atomic 實用情境。

使用 atomic 搭配自定義的型別/類別

接下來會想試看看如果是使用自定義的結構 struct 或類別 class 是否也能使用 atomic 呢?

std-atomic4.cpp
1
TBD

參考
https://en.cppreference.com/w/cpp/atomic/atomic
https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/511579/
https://blog.csdn.net/yockie/article/details/8838686

其它相關文章推薦
C/C++ 新手入門教學懶人包
std::thread 用法與範例
std::deque 用法與範例
std::find 用法與範例
std::mutex 用法與範例
std::unordered_map 用法與範例
std::sort 用法與範例
std::random_shuffle 產生不重複的隨機亂數
std::shared_ptr 用法與範例
std::async 用法與範例

std::filesystem::exists 判斷檔案是否存在的用法與範例

本篇介紹 C++ 的 std::filesystem::exists 用法,並使用 std::filesystem::exists 來判斷檔案是否存在。

假設現在目錄下有 dir 資料夾、text.txt 文字檔、a.out 二進制執行檔,來看看這些範例的結果吧!

要使用 std::filesystem::exists 判斷檔案是否存在的話,需要引入的標頭檔: <filesystem>
各家編譯器還沒正式支援 C++17 前, 可能需要引入 <experimental/filesystem> 標頭檔
引入<filesystem>標頭檔是使用 std::filesystem::exists
引入<experimental/filesystem>標頭檔是使用 std::experimental::filesystem::exists
GCC:g++ 大概要 8 以上才有正式支援 C++17,編譯時要加入-lstdc++fs選項。
Clang:Clang 5.0 應該已經支援。
Visual Studio: Visual Studio 2017 15.3 還是只能使用 std::experimental namespace。

使用範例

std-filesystem-exists.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
// g++ std-filesystem-exists.cpp -o a.out -std=c++11 -lstdc++fs
#include <iostream>
#include <experimental/filesystem>
//#include <filesystem> // C++ 17

using namespace std;
namespace fs = std::experimental::filesystem;
//namespace fs = std::filesystem; // C++ 17

void fileExists(const fs::path& p, fs::file_status s = fs::file_status{})
{
if (fs::status_known(s) ? fs::exists(s) : fs::exists(p))
return true;
return false;
}

bool fileExists(const std::string& path) {
fs::path myfile(path.c_str());
if (fs::exists(myfile)) {
return true;
}
return false;
}

int main() {
cout << fileExists("nothing") << endl;
cout << fileExists("dir") << endl;
cout << fileExists("a.out") << endl;
cout << fileExists("text.txt") << endl;
return 0;
}

輸出結果:

1
2
3
4
0
1
1
1

參考
std::filesystem::exists - cppreference.com
https://en.cppreference.com/w/cpp/filesystem/exists

其它相關文章推薦
C/C++ 新手入門教學懶人包
std::filesystem::create_directory 建立資料夾的用法與範例
std::filesystem::copy 複製檔案的用法與範例
C/C++ 判斷檔案是否存在
C/C++ 判斷資料夾是否存在

std::filesystem::copy 複製檔案的用法與範例

本篇介紹 C++ 的 std::filesystem::copy 用法,並使用 std::filesystem::copy 來複製檔案。

要使用 std::filesystem::copy 複製檔案的話,需要引入的標頭檔: <filesystem>
各家編譯器還沒正式支援 C++17 前, 可能需要引入 <experimental/filesystem> 標頭檔
引入<filesystem>標頭檔是使用 std::filesystem::copy
引入<experimental/filesystem>標頭檔是使用 std::experimental::filesystem::copy
GCC:g++ 大概要 8 以上才有正式支援 C++17,編譯時要加入-lstdc++fs選項。
Clang:Clang 5.0 應該已經支援。
Visual Studio: Visual Studio 2017 15.3 還是只能使用 std::experimental namespace。

基本使用範例

預設複製目錄時不會遞迴式的複製,也就是只有目錄下的檔案會被複製,目錄下的子目錄不會被複製。
若要連目錄下的子目錄一起複製的話可以使用 copy_options::recursive 這個參數。

std-filesystem-copy.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// g++ std-filesystem-copy.cpp -o a.out -std=c++11 -lstdc++fs
#include <iostream>
#include <experimental/filesystem>
//#include <filesystem> // C++17

int main()
{
// The default behavior when copying directories is the non-recursive copy: the files are copied, but not the subdirectories
std::experimental::filesystem::copy("dir1", "dir2");

// While with copy_options::recursive, the subdirectories are also copied, with their content, recursively.
std::experimental::filesystem::copy("dir1", "dir3", std::experimental::filesystem::copy_options::recursive);

// C++17
//std::filesystem::copy("dir1", "dir2");
//std::filesystem::copy("dir1", "dir3", std::filesystem::copy_options::recursive);
}

範例. 處理 C++17 以及尚未支援 C++17 的方式

若想要同時支援新舊版寫法或者是不同平台編譯器的支援程度不相同時,
可以考慮使用 CXX17 這個定義,用這個定義去需分是不是正式支援C++17,
順便在使用 namespace 的方式讓兩種寫法一致化,如下列範例所示:

std-filesystem-copy2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// g++ std-filesystem-copy2.cpp -o a.out -std=c++11 -lstdc++fs
#include <iostream>
#ifdef CXX17 // if this is C++17
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

int main()
{
// The default behavior when copying directories is the non-recursive copy: the files are copied, but not the subdirectories
fs::copy("dir1", "dir2");

// While with copy_options::recursive, the subdirectories are also copied, with their content, recursively.
fs::copy("dir1", "dir3", std::experimental::filesystem::copy_options::recursive);
}

如果來源檔 dir1 不存在會怎樣?
會發生core dumped,如下列輸出:

1
2
3
terminate called after throwing an instance of 'std::experimental::filesystem::v1::__cxx11::filesystem_error'
what(): filesystem error: cannot copy: No such file or directory [dir1] [dir2]
Aborted (core dumped)

參考
std::filesystem::copy - cppreference.com
https://en.cppreference.com/w/cpp/filesystem/copy
c++11 - Are the experimental features of modern C++ reliable for long-term projects? - Stack Overflow
https://stackoverflow.com/questions/43318493/are-the-experimental-features-of-modern-c-reliable-for-long-term-projects
c++ - fatal error: filesystem: No such file or directory - Stack Overflow
https://stackoverflow.com/questions/39231363/fatal-error-filesystem-no-such-file-or-directory/39231488
C++17 Filesystem
https://www.codingame.com/playgrounds/5659/c17-filesystem

其它相關文章推薦
C/C++ 新手入門教學懶人包
std::vector 用法與範例
std::queue 用法與範例
std::deque 用法與範例
std::thread 用法與範例
std::mutex 用法與範例
std::condition_variable 用法與範例

std::filesystem::create_directory 建立資料夾的用法與範例

本篇介紹 C++ 的 std::filesystem::create_directory 用法,並使用 std::filesystem::create_directory 來建立資料夾。

要使用 std::filesystem::create_directory 建立資料夾的話,需要引入的標頭檔: <filesystem>
各家編譯器還沒正式支援 C++17 前, 可能需要引入 <experimental/filesystem> 標頭檔
引入<filesystem>標頭檔是使用 std::filesystem::create_directory
引入<experimental/filesystem>標頭檔是使用 std::experimental::filesystem::create_directory
GCC:g++ 大概要 8 以上才有正式支援 C++17,編譯時要加入-lstdc++fs選項。
Clang:Clang 5.0 應該已經支援。
Visual Studio: Visual Studio 2017 15.3 還是只能使用 std::experimental namespace。

使用範例

在本範例中呼叫create_directory後,指名要建立一個 hello 的資料夾,
如果目錄下沒有 hello 資料夾就會建立一個 hello 的 資料夾,並且回傳 true,
如果目錄下有 hello 資料夾則回傳 false。

std-filesystem-create_directory.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
// g++ std-filesystem-create_directory.cpp -o a.out -std=c++11 -lstdc++fs
#include <iostream>
#include <experimental/filesystem>
//#include <filesystem> // C++ 17

using namespace std;
namespace fs = std::experimental::filesystem;

int main() {
cout << "create hello directory" << endl;
cout << fs::create_directory("hello") << endl;
return 0;
}

輸出結果如下,該目錄下沒有 hello 資料夾且成功建立 hello 資料夾,

1
2
create hello directory
1

參考
std::filesystem::create_directory, std::filesystem::create_directories - cppreference.com
https://en.cppreference.com/w/cpp/filesystem/create_directory

其它相關文章推薦
C/C++ 新手入門教學懶人包
std::filesystem::exists 判斷檔案是否存在的用法與範例
std::filesystem::copy 複製檔案的用法與範例
C/C++ 判斷檔案是否存在
C/C++ 判斷資料夾是否存在

Python 取得cpu使用率

本篇將介紹如何使用 Python 取得cpu使用率,這邊介紹 python 搭配 psutil 模組來取得 cpu 使用率。

pip 安裝 psutil

1
sudo -H pip3 install psutil

使用範例

Python 要取得 cpu 使用率的話可以使用 psutil.cpu_percent 來取得,裡面的參數是要測量的時間間隔,預設是1秒,
這邊的範例使用0.3秒,並且用迴圈跑個10次。

python-get-cpu-usage.py
1
2
3
4
5
6
7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import psutil

print('cpu count: {}'.format(psutil.cpu_count()))
for x in range(10):
print('cpu percent: {}'.format(psutil.cpu_percent(interval=0.3)))

輸出:

1
2
3
4
5
6
7
8
9
10
11
cpu count: 4
cpu percent: 18.2
cpu percent: 16.4
cpu percent: 18.0
cpu percent: 18.5
cpu percent: 19.8
cpu percent: 17.6
cpu percent: 18.0
cpu percent: 17.2
cpu percent: 16.9
cpu percent: 18.6

參考
python获取内存和cpu利用率记录日志文件_PythonBetter Thinker-CSDN博客
https://blog.csdn.net/a6225301/article/details/47092707
Python在Linux下获取CPU温度、使用率、内存使用率、硬盘使用率
运维_小强签名设计 的博客-CSDN博客
https://blog.csdn.net/m0_37739193/article/details/78836827
轉載:python獲取全部程序的CPU、記憶體使用率 | 程式前沿
https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/630751/
[Python系列]Python获取CPU和内存利用率 - 简书
https://www.jianshu.com/p/23c2a518019a
system - How to get current CPU and RAM usage in Python? - Stack Overflow
https://stackoverflow.com/questions/276052/how-to-get-current-cpu-and-ram-usage-in-python

其它相關文章推薦
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace
Python 建立多執行緒 thread
Python OpenCV resize 圖片縮放
Python OpenCV 顯示camera攝影機串流影像
Python 快速建立簡單網頁伺服器 http websever
Python 建立簡單的 Tornado Web
[Python小專案] Tornado+PyAutoGUI 多媒體控制播放的網頁

Python print 格式化輸出與排版

本篇將介紹如何使用 Python print 格式化輸出與排版,在寫 python 程式有時常會用到 print,順便在這邊作個紀錄。

以下內容分為這幾部份,

  • print 基本輸出
  • print 基本輸出 (format用法)
  • print 對齊排版
  • print 對齊排版 (format用法)
  • print 輸出浮點數到小數點兩位
  • print 輸出 % 百分比符號
  • Python print 不換行

print 基本輸出

Python 如果想用 print 輸出字串,可以用下列方式:

1
2
s1 = 'hello'
print('%s world' % s1)

輸出:

1
hello

也可以這樣寫,用 + 來連接字串,可以一直連接下去

1
2
3
s1 = 'hello'
s2 = ' world'
print(s1 + s2)

Python 如果想用 print 輸出字元,可以用 %c 格式化字元輸出的方式:

1
2
c1 = chr(65)
print('%c' % c1)

輸出:

1
A

Python 如果想用 print 輸出整數,可以用 %d 格式化整數輸出的方式:

1
2
n = 123
print('%d' % n)

輸出:

1
123

Python 如果想用 print 輸出浮點數(預設輸出到小數點第六位),可以用 %f 格式化浮點數輸出方式:

1
2
n = 123.4
print('%f' % n)

輸出:

1
123.400000

print 基本輸出 (format用法)

Python 如果想用 print format 輸出字串,可以用下列方式,
分別為 不數字編號,帶數字編號,自訂順序,重複多次輸出

1
2
3
4
5
6
7
s1 = 'hello'
s2 = 'world'

print('{} {}'.format(s1, s2)) # 不數字編號
print('{0} {1}'.format(s1, s2)) # 帶數字編號
print('{1} {0}'.format(s1, s2)) # 自訂順序
print('{0} {1} {0}'.format(s1, s2)) # 重複多次輸出

輸出:

1
2
3
4
5
hello
hello world
hello world
world hello
hello world hello

Python 如果想用 print format 輸出字元,可以用下列方式:

1
2
c1 = chr(65)
print('{}'.format(c1))

Python 如果想用 print format 輸出整數,可以用下列方式:

1
2
n = 123
print('{}'.format(n))

輸出:

1
123

Python 如果想用 print format 輸出浮點數,可以用下列方式:

1
2
n = 123.4
print('{}'.format(n))

輸出:

1
123.4

print 對齊排版

Python 如果想用 print 字串對齊(預設靠右對齊),可以用下列方式:

1
2
s1 = 'hello'
print('[%10s]' % s1)

輸出:

1
[     hello]

Python 如果想用 print 字串靠左對齊,可以用下列方式:

1
2
s1 = 'hello'
print('[%-10s]' % s1)

輸出:

1
[hello     ]

print 對齊排版 (format用法)

Python 如果想用 print format 字串對齊(預設靠左對齊),可以用下列方式:

1
2
s1 = 'hello'
print('[{:10}]'.format(s1))

輸出:

1
[hello     ]

Python 如果想用 print format 字串靠右對齊,可以用下列方式:

1
2
s1 = 'hello'
print('[{:>10}]'.format(s1))

輸出:

1
[     hello]

Python 如果想用 print format 字串置中對齊,可以用下列方式:

1
2
s1 = 'hello'
print('[{:^10}]'.format(s1))

輸出:

1
[  hello   ]

Python 如果想用 print format 字串靠左對齊,可以用下列方式:

1
2
s1 = 'hello'
print('[{:<10}]'.format(s1))

輸出:

1
[hello     ]

print 輸出浮點數到小數點兩位

Python 如果想用 print 輸出浮點數到小數點兩位,例如:20.12,可以用下列這個方式:

1
2
number = 20.1234
print('%.2f' % number)

輸出:

1
20.12

print 輸出 % 百分比符號

Python 如果 print 後面還想輸出 % 百分比符號 percentage,例如:20.12 %,可以這樣寫

1
2
rate = 20.12
print('%.2f' % rate + chr(37))

輸出:

1
20.12%

Python print 不換行

Python print 不換行的話方法如下,就是將結尾的字元設為空,

1
print('hello world', end='')

Python 預設 print 是會換行的,也就是將結尾的字元設為換行字元 '\n',預設跟下面的效果一樣,

1
print('hello world', end='\n')

以上就是 Python print 的介紹,下一篇會來介紹 Python 取得鍵盤輸入

參考
https://www.itread01.com/content/1548549397.html
https://stackoverflow.com/questions/2075128/python-print-all-floats-to-2-decimal-places-in-output
https://www.codespeedy.com/how-to-print-percentage-sign-in-python/
https://stackoverflow.com/questions/5306756/how-to-print-a-percentage-value-in-python

其它相關文章推薦
Python 新手入門教學懶人包
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace
Python 建立多執行緒 thread
Python OpenCV resize 圖片縮放
Python OpenCV 顯示camera攝影機串流影像
Python 快速建立簡單網頁伺服器 http websever
Python 建立簡單的 Tornado Web
[Python小專案] Tornado+PyAutoGUI 多媒體控制播放的網頁