1. 程式人生 > >用量子計算模擬器ProjectQ生成隨機數,並用pytest進行單元測試與覆蓋率測試

用量子計算模擬器ProjectQ生成隨機數,並用pytest進行單元測試與覆蓋率測試

# 技術背景 本文中主要包含有三個領域的知識點:隨機數的應用、量子計算模擬產生隨機數與基於pytest框架的單元測試與覆蓋率測試,這裡先簡單分別介紹一下背景知識。 ## 隨機數的應用 在上一篇介紹[量子態模擬取樣](https://www.cnblogs.com/dechinphy/p/state.html)的演算法中,我們就使用到了隨機數,隨機數在各種蒙特卡洛方法與數值計算中,扮演著非常重要的角色。在金融領域,隨機數則是在加密演算法中扮演重要角色,其風險在於,如果隨機數可被預測,那麼惡意使用者就可以利用這一特點,破解對稱加密甚至是非對稱加密的演算法(非對稱加密如RSA演算法的私鑰的挑選其實也有可能使用到隨機數)。在python程式碼中,可以通過呼叫random庫或者numpy.random庫進行隨機數的生成,僅需要通過如下的程式碼即可實現: ```python import random random_number = random.random() # 產生[0,1)之間的均勻隨機數 import numpy as np random_array = random.randn(10) # 產生10個隨機數並存儲到np格式的一維陣列中 ``` 這些庫所產生的隨機數,往往被認為是不安全的隨機數,其主要特點是通過隨機數生成演算法,結合硬體的一些獨有編號來產生一系列數串。但是隨機數生成演算法一般都是已知的,因此還是有一定的潛在風險。有一個python庫函式叫`secrets`可以產生"安全隨機數",其特點在於不僅利用了一些硬體系統獨有資訊,如ip和MAC等,主要還利用了系統熵源來生成隨機數,增強了所產生隨機數的不可預測性。關於`secrets`的使用方法, 可以參考其[官方文件](https://docs.python.org/3/library/secrets.html#random-numbers)。但是,即使是這裡所謂的`安全隨機數`,也並不是`真隨機數`,真隨機數的產生不依賴於演算法。 ## 量子計算與隨機數 前面寫過一篇部落格介紹[兩位元量子系統的模擬](https://www.cnblogs.com/dechinphy/p/magic.html),讀者可以從中瞭解到量子計算的一些基本原理與模擬實現。而另一篇關於[量子線路模擬](https://www.cnblogs.com/dechinphy/p/circuit.html)的部落格,則介紹了關於開源量子計算框架ProjectQ的一些基本使用方法,在這篇文章中我們也會使用到。通過量子硬體,我們可以直接讀取一系列的隨機串,由於這些隨機串是由硬體直接給出來的結果,不是通過演算法來生成的,因此是完成不可預測的,被稱為"真隨機數"。 ## 基於pytest的python單元測試框架 在使用python程式設計實現演算法時,需要對演算法函式或者類進行功能驗證,這就需要寫測試用例。python第三方庫pytest提供了非常好的自動化測試的功能,配合html外掛和覆蓋率測試外掛,還可以進行更多的測試以及更好的展示測試的結果。 # 量子計算產生隨機數 量子計算是基於量子疊加與量子糾纏兩種特性進行計算的方案,其結合量子演算法的複雜性優勢,在量子處理器上可以實現經典計算機無法在有效時間內完成的任務,一般稱之為量子優越性。量子疊加是對量子位元重要特性的一個總結,如下圖所示(圖片來自於參考連結1),區分於經典位元,量子位元不僅可以表示`0`和`1`,還可以表示處於`0`和`1`之間的狀態,比如`0.5`,`0.2243`等等。這些狀態我們不能直接讀取,在硬體上我們只能夠讀取到`0`或者`1`兩種狀態,這跟經典位元是一樣的。區別在於,即使我們不改變數子位元的狀態,不同的測試卻會給出不同的結果,而`0.5`等中間狀態,則表示的是出現`0`或者`1`狀態分別的概率。 ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228221328677-1165684319.png) 由於量子測量會導致量子態的坍縮,也就是說,每一次測量之後,都需要重新制備量子態。而製備一個產生隨機數的量子態,我們可以用如下所示的$H$量子門操作來實現。其具體的矩陣表述可以參考[這篇部落格](https://www.cnblogs.com/dechinphy/p/circuit.html),量子計算本質上就是用特殊的硬體方法,快速的實現大規模的矩陣運算,這也是其展現量子優勢的來源。 ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228214704151-1207120775.png) 這裡我們直接使用開源量子計算框架ProjectQ來實現這個門操作,就省去了自己去模擬實習的繁瑣操作: ```python # random_number.py from projectq import MainEngine from projectq.ops import H, Measure def random_number_generator(): eng = MainEngine() qubit = eng.allocate_qubit() H | qubit eng.flush() Measure | qubit random_number = int(qubit) eng.flush(deallocate_qubits=True) return random_number if __name__ == '__main__': random_number = random_number_generator() print ('Random number generated by quantum simulator is: {}'.format(random_number)) ``` 這裡順帶的介紹下ProjectQ的一些操作實現的方法,在ProjectQ中將眾多的量子位元作為暫存器來進行呼叫,這些暫存器都在給定的engine下賦予了各種操作,如量子門操作、列印線路、編譯優化等。程式設計框架與實際的量子位元並不在架構上的同一個層次,每次傳送指令都是通過eng.flush()打包進行編譯優化之後,再傳送到後端去逐一執行。因此如果要測量量子位元(在ProjectQ模擬器中必須只能全部執行測量操作,不能只測量其中的某一個部分),或者是讀取某一個量子態的概率時,都需要先執行eng.flush()才行。接下來簡單看下上述程式碼的執行效果: ```bash [dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 1 [dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 1 [dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 0 [dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 0 [dechin@dechin-manjaro pytest]$ python3 random_number.py Random number generated by quantum simulator is: 1 ``` 在這個案例中,每一次都會產生一個新的隨機數0或者1,並且在量子位元使用結束之後,通過eng.flush(deallocate_qubits=True)可以初始化該暫存器,所有的振幅和測量結果都會被丟棄。 ## 注意!!! 需要注意的是,由於這裡我們是使用了模擬器來模擬量子計算機的行為,因此得到的隨機數結果還是偽隨機數。只有當這一串程式碼執行在量子處理器上時,我們才能得到真隨機數。 # pytest測試 ## 安裝pytest庫 首先我們可以通過pip來更新安裝pytest: ```bash [dechin@dechin-manjaro pytest]$ python3 -m pip install -U pytest Collecting pytest Downloading pytest-6.2.2-py3-none-any.whl (280 kB) |████████████████████████████████| 280 kB 464 kB/s Requirement already satisfied, skipping upgrade: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (1.1.1) Requirement already satisfied, skipping upgrade: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (0.13.1) Requirement already satisfied, skipping upgrade: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (20.3.0) Requirement already satisfied, skipping upgrade: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (0.10.1) Requirement already satisfied, skipping upgrade: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (20.4) Requirement already satisfied, skipping upgrade: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest) (1.9.0) Requirement already satisfied, skipping upgrade: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest) (2.4.7) Requirement already satisfied, skipping upgrade: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest) (1.15.0) Installing collected packages: pytest Attempting uninstall: pytest Found existing installation: pytest 6.2.1 Uninstalling pytest-6.2.1: Successfully uninstalled pytest-6.2.1 Successfully installed pytest-6.2.2 ``` 安裝完成後,可以通過如下指令來檢視安裝的pytest版本: ```bash [dechin@dechin-manjaro pytest]$ pytest --version pytest 6.2.2 ``` ## pytest單元測試用例撰寫 根據前面一個章節中的`random_number.py`檔案,我們可以對照的寫一個簡單測試用例: ``` # test_random_number.py import pytest from random_number import random_number_generator as rng def test_random_number_generator(): for i in range(10): random_number = rng() assert random_number == 0 or random_number == 1 ``` 該測試用例的含義為:匯入rng函式之後,測試10次該函式的返回值,所返回的值必須是0或者1的隨機數,如果輸出了這兩個數字以外的返回結果,那麼說明這個隨機數產生器功能上存在問題。基於pytest的測試程式碼可以通過如下的指令來執行: ```bash [dechin@dechin-20n2s01200 pytest]$ py.test =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] ============================================= warnings summary ============================================= ../../../anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:118 /home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:118: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray. return np.matrix([[1, 0], [0, 1j]]) ../../../anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:133 /home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:133: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray. return np.matrix([[1, 0], [0, cmath.exp(1j * cmath.pi / 4)]]) test_random_number.py: 40 warnings /home/dechin/anaconda3/lib/python3.8/site-packages/projectq/ops/_gates.py:69: PendingDeprecationWarning: the matrix subclass is not the recommended way to represent matrices or deal with linear algebra (see https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). Please adjust your code to use regular ndarray. return 1. / cmath.sqrt(2.) * np.matrix([[1, 1], [1, -1]]) -- Docs: https://docs.pytest.org/en/stable/warnings.html ====================================== 1 passed, 42 warnings in 0.50s ====================================== ``` 從返回的結果來看,出現了`1 passed`而沒有failed,說明所有的測試用例都已經執行成功了,但是這裡存在不少的告警`warnings`資訊。 ## pytest初始化配置檔案 在上一節的測試結果中,我們發現有非常多的測試告警。假如我們確認這些告警資訊可以忽略,那麼我們可以通過在指令中配置忽略告警資訊,或者直接使用這裡介紹的`pytest.ini`來忽略相應的告警資訊: ```bash # pytest.ini [pytest] filterwarnings = ignore::PendingDeprecationWarning ``` 在當前目錄下的`ini`配置檔案中,我們添加了`PendingDeprecationWarning`作為忽略項,然後我們再回頭看一下上述用例的測試結果: ```bash [dechin@dechin-manjaro pytest]$ py.test =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.ini plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] ============================================ 1 passed in 0.50s ============================================= ``` 這裡返回的結果中就沒有告警資訊了。 ## pytest生成html格式報告 為了更好的展現測試的結果,這裡我們需要先安裝一個元件`pytest-html`: ```bash [dechin@dechin-manjaro pytest]$ python3 -m pip install pytest-html Collecting pytest-html Downloading pytest_html-3.1.1-py3-none-any.whl (14 kB) Collecting pytest-metadata Downloading pytest_metadata-1.11.0-py2.py3-none-any.whl (10 kB) Requirement already satisfied: pytest!=6.0.0,>=5.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest-html) (6.2.1) Requirement already satisfied: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (20.3.0) Requirement already satisfied: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (1.9.0) Requirement already satisfied: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (0.10.1) Requirement already satisfied: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (20.4) Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (0.13.1) Requirement already satisfied: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest!=6.0.0,>=5.0->pytest-html) (1.1.1) Requirement already satisfied: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest!=6.0.0,>=5.0->pytest-html) (1.15.0) Requirement already satisfied: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest!=6.0.0,>=5.0->pytest-html) (2.4.7) Installing collected packages: pytest-metadata, pytest-html Successfully installed pytest-html-3.1.1 pytest-metadata-1.11.0 ``` 安裝成功後,執行如下指令,可以在當前目錄下生成一個指定檔名的html檔案,如下圖所示,就比較全面且美觀的展示了測試中的資訊: ```bash [dechin@dechin-manjaro pytest]$ py.test --html=pytest_report.html =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.ini plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] --------- generated html file: file:///home/dechin/projects/2021-python/pytest/pytest_report.html ---------- ============================================ 1 passed in 0.51s ============================================= ``` ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228214751932-2143574590.png) 不過在問題數量並不是很多的情況下,直接看命令列輸出也是比較方便的。 ## pytest覆蓋率測試 在一個python倉庫中我們有可能有非常多的函式、類和檔案等,為了保障結果的準確性,我們需要能夠給出一個可信的覆蓋率測試的結論,只有當覆蓋率達到100%時,我們才能認為測試工作已經比較全面的考慮。當然,覆蓋率100%的測試,其實並不能保障100%的不出問題,這就是另外的話題了。首先我們又需要補充安裝一個元件`pytest-cov`: ```bash [dechin@dechin-manjaro pytest]$ python3 -m pip install pytest-cov Collecting pytest-cov Downloading pytest_cov-2.11.1-py2.py3-none-any.whl (20 kB) Collecting coverage>=5.2.1 Downloading coverage-5.4-cp38-cp38-manylinux2010_x86_64.whl (245 kB) |████████████████████████████████| 245 kB 15 kB/s Requirement already satisfied: pytest>=4.6 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest-cov) (6.2.1) Requirement already satisfied: attrs>=19.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (20.3.0) Requirement already satisfied: packaging in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (20.4) Requirement already satisfied: iniconfig in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (1.1.1) Requirement already satisfied: toml in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (0.10.1) Requirement already satisfied: py>=1.8.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (1.9.0) Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pytest>=4.6->pytest-cov) (0.13.1) Requirement already satisfied: six in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest>=4.6->pytest-cov) (1.15.0) Requirement already satisfied: pyparsing>=2.0.2 in /home/dechin/anaconda3/lib/python3.8/site-packages (from packaging->pytest>=4.6->pytest-cov) (2.4.7) Installing collected packages: coverage, pytest-cov Successfully installed coverage-5.4 pytest-cov-2.11.1 ``` 然後在當前目錄下執行以下指令: ```bash [dechin@dechin-manjaro pytest]$ py.test --cov=random_number ./ --cov-report=html =========================================== test session starts ============================================ platform linux -- Python 3.8.5, pytest-6.2.1, py-1.9.0, pluggy-0.13.1 rootdir: /home/dechin/projects/2021-python/pytest, configfile: pytest.ini plugins: cov-2.11.1, metadata-1.11.0, html-3.1.1 collected 1 item test_random_number.py . [100%] ----------- coverage: platform linux, python 3.8.5-final-0 ----------- Coverage HTML written to dir htmlcov ============================================ 1 passed in 0.76s ============================================= ``` 這裡會提示我們去`htmlcov`目錄下找測試報告,我們開啟相應的`index.html`檔案,效果如下: ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228214850576-396566691.png) 這裡我們看到`random_number.py`檔案的測試覆蓋率為86%,我們可以點開連結檢視剩下未覆蓋的測試是什麼內容: ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228214921707-838032453.png) 原來是main函式中的幾行指令沒有被測試到,一般我們在正式倉庫中,是需要去掉main函式的,如果不是測試檔案的話。 # 使用flake8進行python編碼規範檢查 首先我們還是使用pip來直接安裝`flake8`元件,其集成了PEP8的python編碼規範: ```bash [dechin@dechin-manjaro pytest]$ python3 -m pip install -U flake8 Requirement already up-to-date: flake8 in /home/dechin/anaconda3/lib/python3.8/site-packages (3.8.4) Requirement already satisfied, skipping upgrade: mccabe<0.7.0,>=0.6.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8) (0.6.1) Requirement already satisfied, skipping upgrade: pyflakes<2.3.0,>=2.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8) (2.2.0) Requirement already satisfied, skipping upgrade: pycodestyle<2.7.0,>=2.6.0a1 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8) (2.6.0) ``` 檢視安裝的flake8版本號: ```bash [dechin@dechin-manjaro pytest]$ flake8 --version 3.8.4 (mccabe: 0.6.1, pycodestyle: 2.6.0, pyflakes: 2.2.0) CPython 3.8.5 on Linux ``` 使用方式較為簡單,在當前目錄下直接執行flake8即可,檢查項會以當前路徑為rootdir,遞迴的進行檢索: ```bash [dechin@dechin-manjaro pytest]$ flake8 ./test_random_number.py:2:1: F401 'pytest' imported but unused ./test_random_number.py:5:1: E302 expected 2 blank lines, found 1 ./random_number.py:5:1: E302 expected 2 blank lines, found 1 ./random_number.py:15:1: E305 expected 2 blank lines after class or function definition, found 1 ./random_number.py:17:10: E211 whitespace before '(' ./random_number.py:17:80: E501 line too long (87 > 79 characters) ``` 假如我們不想包含測試用例的風格檢查,我們可以在命令列中遮蔽相關檔案,或者建立配置檔案,在配置檔案中遮蔽相關檔案,這裡介紹後者的使用方法: ```bash # .flake8 [flake8] exclude = ./test* ``` 這個配置的意義在於,將當前目錄下,所有以test開頭的檔案,都將會忽略python編碼規範的檢查,配置檔案支援萬用字元的表達形式。接下來看下最新的執行結果: ```bash [dechin@dechin-manjaro pytest]$ flake8 ./random_number.py:5:1: E302 expected 2 blank lines, found 1 ./random_number.py:15:1: E305 expected 2 blank lines after class or function definition, found 1 ./random_number.py:17:10: E211 whitespace before '(' ./random_number.py:17:80: E501 line too long (87 > 79 characters) ``` 我們發現前面出現的關於測試用例中的編碼規範,已經不在這個列表的範圍了。這個列表中的問題我們一般最好是處理下,但是如果遇到一些判斷不需要處理的規範,則同樣可以在配置檔案中新增相應的規範ID,這裡僅作示例使用,前面顯示的編碼規範問題後面都會改。如下所示就是兩個忽略: ```bash # .flake8 [flake8] exclude = ./test* ignore = E302, E305 ``` 對應的執行結果如下所示: ```bash [dechin@dechin-manjaro pytest]$ flake8 ./random_number.py:17:10: E211 whitespace before '(' ./random_number.py:17:80: E501 line too long (87 > 79 characters) ``` 我們發現被忽略的問題已經沒有顯示了。flake8還有一個特點,是可以配置`max-complexity`,其採用的基本複雜性計算方法為McCabe度量法,可以參考[這篇部落格](https://blog.csdn.net/t_1007/article/details/53034408)中的介紹內容,這裡就不過多的贅述。為了更加美觀簡明的看到輸出的結果,我們可以補充安裝一個元件`flake8-html`: ```bash [dechin@dechin-manjaro pytest]$ python3 -m pip install flake8-html Collecting flake8-html Downloading flake8_html-0.4.1-py2.py3-none-any.whl (13 kB) Requirement already satisfied: pygments>=2.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (2.7.2) Requirement already satisfied: flake8>=3.3.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (3.8.4) Requirement already satisfied: jinja2>=2.9.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (2.11.2) Requirement already satisfied: importlib-metadata in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8-html) (2.0.0) Requirement already satisfied: pycodestyle<2.7.0,>=2.6.0a1 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8>=3.3.0->flake8-html) (2.6.0) Requirement already satisfied: mccabe<0.7.0,>=0.6.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8>=3.3.0->flake8-html) (0.6.1) Requirement already satisfied: pyflakes<2.3.0,>=2.2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from flake8>=3.3.0->flake8-html) (2.2.0) Requirement already satisfied: MarkupSafe>=0.23 in /home/dechin/anaconda3/lib/python3.8/site-packages (from jinja2>=2.9.0->flake8-html) (1.1.1) Requirement already satisfied: zipp>=0.5 in /home/dechin/anaconda3/lib/python3.8/site-packages (from importlib-metadata->flake8-html) (3.4.0) Installing collected packages: flake8-html Successfully installed flake8-html-0.4.1 ``` 使用方法如下: ```bash [dechin@dechin-20n2s01200 pytest]$ flake8 --format=html --htmldir=flake-report ./random_number.py has issues: medium: 4 ``` 在當前目錄執行後,相關的規範的issue就不會在命令列裡面逐一顯示,都在flake-report目錄下的index.html中可以檢視: ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228234700674-1081519054.png) 我們可以點選進入相應檔案的issue清單中去檢視: ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228234720845-212818278.png) 可以點選每一個issue,展開內容中包含了issue所對應行的程式碼內容: ![](https://img2020.cnblogs.com/blog/2277440/202102/2277440-20210228234743208-1827795154.png) 經過一番修改之後,我們得到的flake8配置檔案和原始碼檔案如下: ```bash # .flake8 [flake8] exclude = ./test* ignore = W391 ``` ```python # random_number.py from projectq import MainEngine from projectq.ops import H, Measure def random_number_generator(): eng = MainEngine() qubit = eng.allocate_qubit() H | qubit eng.flush() Measure | qubit random_number = int(qubit) eng.flush(deallocate_qubits=True) return random_number if __name__ == '__main__': random_number = random_number_generator() print('Random number generated by quantum simulator is:\ {}'.format(random_number)) ``` 最終我們的目的是使得flake8執行的issue清零: ```bash [dechin@dechin-manjaro pytest]$ flake8 --format=html --htmldir=flake-report [dechin@dechin-manjaro pytest]$ ``` # 總結概要 本文通過引入一個隨機數生成器的案例,介紹了在量子計算中產生真隨機數的方案,同時給出了量子計算模擬實現。藉此機會也同時介紹了python的單元測試庫pytest的一些常規和擴充套件使用方法,以及python的編碼規範測試庫flake8的基本使用方法,希望能夠對大家有所啟發以及幫助。 # 版權宣告 本文首發連結為:https://www.cnblogs.com/dechinphy/p/random_number_test.html 作者ID:DechinPhy 更多原著文章請參考:https://www.cnblogs.com/dechinphy/ # 參考連結 1. https://cn.bing.com/images/search?view=detailV2&ccid=X1pIP1mm&id=0CF2CDDD1C700A051F3FEB4701669068CE05B9FA&thid=OIP.X1pIP1mmVKohO5UC1CvbuQHaED&mediaurl=https%3a%2f%2fth.bing.com%2fth%2fid%2fR5f5a483f59a654aa213b9502d42bdbb9%3frik%3d%252brkFzmiQZgFH6w%26riu%3dhttp%253a%252f%252fwww.supernovapcrepair.co.uk%252fimages%252fquantum%2bsuperposition.png%26ehk%3dEt3zyrD9NqYgaMFwpPb%252bcZAohbR0ERpeRfCEkgKy6i0%253d%26risl%3d%26pid%3dImgRaw&exph=199&expw=363&q=quantum+superposition&simid=608026555008484117&ck=E74E3E03947D89427ED1A5352402AADB&selectedIndex=3&FORM=IRPRST&aja