Tag: pip

  • Tổng quan thư viện Underthesea – bộ công cụ mã nguồn mở xử lý ngôn ngữ tự nhiên tiếng Việt

    Tổng quan thư viện Underthesea – bộ công cụ mã nguồn mở xử lý ngôn ngữ tự nhiên tiếng Việt

    Giới thiệu thư viện Underthesea – bộ công cụ mã nguồn mở xử lý ngôn ngữ tự nhiên tiếng Việt

    Mở đầu

    Underthesea là một toolkit hỗ trợ cho việc nghiên cứu và phát triển xử lý ngôn ngữ tự nhiên tiếng Việt. Underthesea ra đời vào tháng 3 năm 2017, trong bối cảnh ở Việt Nam đã có một số toolkit khá tốt như vn.vitk, pyvi, nhưng vẫn thiếu một toolkit hoàn chỉnh, mã nguồn mở, dễ dàng cài đặt và sử dụng như các sản phẩm tương đương đối với tiếng Anh như nltk, polyglot, spacy.

    Trong bài viết này chúng ta sẽ tìm hiểu sơ qua về Underthesea và một số cách sử dụng của nó.

    Underthesea là :

    1. Một bộ công cụ NLP tiếng Việt <br> Underthesea là một mã nguồn mở bằng Python bao gồm các bộ dữ liệu (data sets) và các hướng dẫn hỗ trợ nghiên cứu và phát triển trong xử lý ngôn ngữ tự nhiên tiếng Việt (Vietnamese Natural Language Processing). Nó cung cấp các API cực kỳ dễ dàng để áp dụng các mô hình pretrained NLP cho văn bản tiếng Việt, chẳng hạn như phân đoạn từ, gắn thẻ một phần giọng nói(PoS), nhận dạng thực thể có tên (NER), phân loại văn bản và phân tích cú pháp phụ thuộc.

    2. Một thư viện Pytorch <br> Underthesea được hỗ trợ bởi một trong những thư viên học sâu phổ biến nhất, Pytorch, giúp nó dễ dàng train các mô hình học sâu và thử nghiệp các phương pháp tiếp cận mới bằng cách sử dụng các Module và Class của Underthesea

    3. Một phần mềm mã nguồn mở <br> Underthesea được công bố theo giấy phép GNU General Public License v3.0. Các quyền của giấy phép này có điều kiện là cung cấp mã nguồn hoàn chỉnh của các tác phẩm được cấp phép và sửa đổi, bao gồm các tác phẩm lớn hơn sử dụng tác phẩm được cấp phép, theo cùng một giấy phép.

    Cài đặt

    Để cài đặt underthesea :

    $ pip install underthesea
    

    Hướng dẫn

    1. Phân đoạn câu (Sentence Segmentation)
    >>> from underthesea import sent_tokenize
    >>> text = 'Taylor cho biết lúc đầu cô cảm thấy ngại với cô bạn thân Amanda nhưng rồi mọi thứ trôi qua nhanh chóng. Amanda cũng thoải mái với mối quan hệ này.'
    
    >>> sent_tokenize(text)
    [
      "Taylor cho biết lúc đầu cô cảm thấy ngại với cô bạn thân Amanda nhưng rồi mọi thứ trôi qua nhanh chóng.",
      "Amanda cũng thoải mái với mối quan hệ này."
    ]
    
    1. Phân đoạn từ (Word Segmentation)
    >>> from underthesea import word_tokenize
    >>> sentence = 'Chàng trai 9X Quảng Trị khởi nghiệp từ nấm sò'
    
    >>> word_tokenize(sentence)
    ['Chàng trai', '9X', 'Quảng Trị', 'khởi nghiệp', 'từ', 'nấm', 'sò']
    
    >>> word_tokenize(sentence, format="text")
    'Chàng_trai 9X Quảng_Trị khởi_nghiệp từ nấm sò'
    
    1. Gán nhãn POS
    >>> from underthesea import pos_tag
    >>> pos_tag('Chợ thịt chó nổi tiếng ở Sài Gòn bị truy quét')
    [('Chợ', 'N'),
     ('thịt', 'N'),
     ('chó', 'N'),
     ('nổi tiếng', 'A'),
     ('ở', 'E'),
     ('Sài Gòn', 'Np'),
     ('bị', 'V'),
     ('truy quét', 'V')]
    
    1. Chunking
    >>> text = 'Bác sĩ bây giờ có thể thản nhiên báo tin bệnh nhân bị ung thư?'
    >>> chunk(text)
    [('Bác sĩ', 'N', 'B-NP'),
     ('bây giờ', 'P', 'I-NP'),
     ('có thể', 'R', 'B-VP'),
     ('thản nhiên', 'V', 'I-VP'),
     ('báo tin', 'N', 'B-NP'),
     ('bệnh nhân', 'N', 'I-NP'),
     ('bị', 'V', 'B-VP'),
     ('ung thư', 'N', 'I-VP'),
     ('?', 'CH', 'O')]
    
    1. Phân tích cú pháp phụ thuộc
    >>> from underthesea import dependency_parse
    >>> text = 'Tối 29/11, Việt Nam thêm 2 ca mắc Covid-19'
    >>> dependency_parse(text)
    [('Tối', 5, 'obl:tmod'),
     ('29/11', 1, 'flat:date'),
     (',', 1, 'punct'),
     ('Việt Nam', 5, 'nsubj'),
     ('thêm', 0, 'root'),
     ('2', 7, 'nummod'),
     ('ca', 5, 'obj'),
     ('mắc', 7, 'nmod'),
     ('Covid-19', 8, 'nummod')]
    
    1. Gán nhãn thực thể có tên (Named Entity Recognition)
    >>> from underthesea import ner
    >>> text = 'Chưa tiết lộ lịch trình tới Việt Nam của Tổng thống Mỹ Donald Trump'
    >>> ner(text)
    [('Chưa', 'R', 'O', 'O'),
     ('tiết lộ', 'V', 'B-VP', 'O'),
     ('lịch trình', 'V', 'B-VP', 'O'),
     ('tới', 'E', 'B-PP', 'O'),
     ('Việt Nam', 'Np', 'B-NP', 'B-LOC'),
     ('của', 'E', 'B-PP', 'O'),
     ('Tổng thống', 'N', 'B-NP', 'O'),
     ('Mỹ', 'Np', 'B-NP', 'B-LOC'),
     ('Donald', 'Np', 'B-NP', 'B-PER'),
     ('Trump', 'Np', 'B-NP', 'I-PER')]
    
    1. Phân loại văn bản
    >>> from underthesea import classify
    
    >>> classify('HLV đầu tiên ở Premier League bị sa thải sau 4 vòng đấu')
    ['The thao']
    
    >>> classify('Hội đồng tư vấn kinh doanh Asean vinh danh giải thưởng quốc tế')
    ['Kinh doanh']
    
    >> classify('Lãi suất từ BIDV rất ưu đãi', domain='bank')
    ['INTEREST_RATE']
    
    1. Phân tích cảm xúc
    >>> from underthesea import sentiment
    
    >>> sentiment('hàng kém chất lg,chăn đắp lên dính lông lá khắp người. thất vọng')
    negative
    >>> sentiment('Sản phẩm hơi nhỏ so với tưởng tượng nhưng chất lượng tốt, đóng gói cẩn thận.')
    positive
    
    >>> sentiment('Đky qua đường link ở bài viết này từ thứ 6 mà giờ chưa thấy ai lhe hết', domain='bank')
    ['CUSTOMER_SUPPORT#negative']
    >>> sentiment('Xem lại vẫn thấy xúc động và tự hào về BIDV của mình', domain='bank')
    ['TRADEMARK#positive']
    
    1. Tài nguyên NLP tiếng Việt

    Danh sách tài nguyên

    $ underthesea list-data
    | Name                | Type        | License | Year | Directory                    |
    |---------------------+-------------+---------+------+------------------------------|
    | UIT_ABSA_RESTAURANT | Sentiment   | Open    | 2021 | datasets/UIT_ABSA_RESTAURANT |
    | UIT_ABSA_HOTEL      | Sentiment   | Open    | 2021 | datasets/UIT_ABSA_HOTEL      |
    | SE_Vietnamese-UBS   | Sentiment   | Open    | 2020 | datasets/SE_Vietnamese-UBS   |
    | CP_Vietnamese-UNC   | Plaintext   | Open    | 2020 | datasets/CP_Vietnamese-UNC   |
    | DI_Vietnamese-UVD   | Dictionary  | Open    | 2020 | datasets/DI_Vietnamese-UVD   |
    | UTS2017-BANK        | Categorized | Open    | 2017 | datasets/UTS2017-BANK        |
    | VNTQ_SMALL          | Plaintext   | Open    | 2012 | datasets/LTA                 |
    | VNTQ_BIG            | Plaintext   | Open    | 2012 | datasets/LTA                 |
    | VNESES              | Plaintext   | Open    | 2012 | datasets/LTA                 |
    | VNTC                | Categorized | Open    | 2007 | datasets/VNTC                |
    
    $ underthesea list-data --all
    

    Download tài nguyên

    $ underthesea download-data VNTC
    100%|██████████| 74846806/74846806 [00:09<00:00, 8243779.16B/s]
    Resource VNTC is downloaded in ~/.underthesea/datasets/VNTC folder
    

    Các tính năng sắp ra mắt

    • Dịch máy
    • Chuyển văn bản thành giọng nói
    • Nhận dạng giọng nói tự động

    Kết bài

    Với Underthesea, chúng ta có thể dễ dàng cài đặt, sử dụng và tiết kiệm được lượng lớn thời gian thay vì phải gán nhãn bằng tay. Underthesea cũng là thư viện đắc lực hỗ trợ xử lý dữ liệu đầu vào cho rất nhiều bài toán khác.

    Cảm ơn các bạn đã giành thời gian đọc.

    Tham khảo: https://pypi.org/project/underthesea/

  • Tổng quan về Underthesea

    # **Giới thiệu thư viện Underthesea – bộ công cụ mã nguồn mở xử lý ngôn ngữ tự nhiên tiếng Việt**
    ## **Mở đầu**
    Underthesea là một toolkit hỗ trợ cho việc nghiên cứu và phát triển xử lý ngôn ngữ tự nhiên tiếng Việt. Underthesea ra đời vào tháng 3 năm 2017, trong bối cảnh ở Việt Nam đã có một số toolkit khá tốt như vn.vitk, pyvi, nhưng vẫn thiếu một toolkit hoàn chỉnh, mã nguồn mở, dễ dàng cài đặt và sử dụng như các sản phẩm tương đương đối với tiếng Anh như nltk, polyglot, spacy.
    Trong bài viết này chúng ta sẽ tìm hiểu sơ qua về Underthesea và một số cách sử dụng của nó.## **Underthesea** là : 1.  **Một bộ công cụ NLP tiếng Việt** <br>Underthesea là một mã nguồn mở bằng Python bao gồm các bộ dữ liệu (data sets) và các hướng dẫn hỗ trợ nghiên cứu và phát triển trong xử lý ngôn ngữ tự nhiên tiếng Việt ([Vietnamese Natural Language Processing](https://github.com/undertheseanlp/underthesea)). Nó cung cấp các API cực kỳ dễ dàng để áp dụng các mô hình pretrained NLP cho văn bản tiếng Việt, chẳng hạn như phân đoạn từ, gắn thẻ một phần giọng nói(PoS), nhận dạng thực thể có tên (NER), phân loại văn bản và phân tích cú pháp phụ thuộc.
    2. **Một thư viện Pytorch** <br>Underthesea được hỗ trợ bởi một trong những thư viên học sâu phổ biến nhất, [Pytorch](https://pytorch.org/), giúp nó dễ dàng train các mô hình học sâu và thử nghiệp các phương pháp tiếp cận mới bằng cách sử dụng các Module và Class của Underthesea
    3. **Một phần mềm mã nguồn mở** <br>Underthesea được công bố theo giấy phép GNU General Public License v3.0. Các quyền của giấy phép này có điều kiện là cung cấp mã nguồn hoàn chỉnh của các tác phẩm được cấp phép và sửa đổi, bao gồm các tác phẩm lớn hơn sử dụng tác phẩm được cấp phép, theo cùng một giấy phép.
    ### **Cài đặt**
    Để cài đặt underthesea :“`$ pip install underthesea“`
    ### **Hướng dẫn**
    1. **Phân đoạn câu** (Sentence Segmentation)“`>>> from underthesea import sent_tokenize>>> text = ‘Taylor cho biết lúc đầu cô cảm thấy ngại với cô bạn thân Amanda nhưng rồi mọi thứ trôi qua nhanh chóng. Amanda cũng thoải mái với mối quan hệ này.’
    >>> sent_tokenize(text)[  “Taylor cho biết lúc đầu cô cảm thấy ngại với cô bạn thân Amanda nhưng rồi mọi thứ trôi qua nhanh chóng.”,  “Amanda cũng thoải mái với mối quan hệ này.”]“`
    2. **Phân đoạn từ** (Word Segmentation)“`>>> from underthesea import word_tokenize>>> sentence = ‘Chàng trai 9X Quảng Trị khởi nghiệp từ nấm sò’
    >>> word_tokenize(sentence)[‘Chàng trai’, ‘9X’, ‘Quảng Trị’, ‘khởi nghiệp’, ‘từ’, ‘nấm’, ‘sò’]
    >>> word_tokenize(sentence, format=”text”)’Chàng_trai 9X Quảng_Trị khởi_nghiệp từ nấm sò’“`
    3. **Gán nhãn POS**“`>>> from underthesea import pos_tag>>> pos_tag(‘Chợ thịt chó nổi tiếng ở Sài Gòn bị truy quét’)[(‘Chợ’, ‘N’), (‘thịt’, ‘N’), (‘chó’, ‘N’), (‘nổi tiếng’, ‘A’), (‘ở’, ‘E’), (‘Sài Gòn’, ‘Np’), (‘bị’, ‘V’), (‘truy quét’, ‘V’)]“`
    4. **Chunking**“`>>> from underthesea import chunk>>> text = ‘Bác sĩ bây giờ có thể thản nhiên báo tin bệnh nhân bị ung thư?’>>> chunk(text)[(‘Bác sĩ’, ‘N’, ‘B-NP’), (‘bây giờ’, ‘P’, ‘I-NP’), (‘có thể’, ‘R’, ‘B-VP’), (‘thản nhiên’, ‘V’, ‘I-VP’), (‘báo tin’, ‘N’, ‘B-NP’), (‘bệnh nhân’, ‘N’, ‘I-NP’), (‘bị’, ‘V’, ‘B-VP’), (‘ung thư’, ‘N’, ‘I-VP’), (‘?’, ‘CH’, ‘O’)]“`
    5. **Phân tích cú pháp phụ thuộc**“`>>> from underthesea import dependency_parse>>> text = ‘Tối 29/11, Việt Nam thêm 2 ca mắc Covid-19’>>> dependency_parse(text)[(‘Tối’, 5, ‘obl:tmod’), (’29/11′, 1, ‘flat:date’), (‘,’, 1, ‘punct’), (‘Việt Nam’, 5, ‘nsubj’), (‘thêm’, 0, ‘root’), (‘2’, 7, ‘nummod’), (‘ca’, 5, ‘obj’), (‘mắc’, 7, ‘nmod’), (‘Covid-19’, 8, ‘nummod’)]“`
    6. **Gán nhãn thực thể có tên** (Named Entity Recognition)“`>>> from underthesea import ner>>> text = ‘Chưa tiết lộ lịch trình tới Việt Nam của Tổng thống Mỹ Donald Trump’>>> ner(text)[(‘Chưa’, ‘R’, ‘O’, ‘O’), (‘tiết lộ’, ‘V’, ‘B-VP’, ‘O’), (‘lịch trình’, ‘V’, ‘B-VP’, ‘O’), (‘tới’, ‘E’, ‘B-PP’, ‘O’), (‘Việt Nam’, ‘Np’, ‘B-NP’, ‘B-LOC’), (‘của’, ‘E’, ‘B-PP’, ‘O’), (‘Tổng thống’, ‘N’, ‘B-NP’, ‘O’), (‘Mỹ’, ‘Np’, ‘B-NP’, ‘B-LOC’), (‘Donald’, ‘Np’, ‘B-NP’, ‘B-PER’), (‘Trump’, ‘Np’, ‘B-NP’, ‘I-PER’)]“`
    7. **Phân loại văn bản**“`>>> from underthesea import classify
    >>> classify(‘HLV đầu tiên ở Premier League bị sa thải sau 4 vòng đấu’)[‘The thao’]
    >>> classify(‘Hội đồng tư vấn kinh doanh Asean vinh danh giải thưởng quốc tế’)[‘Kinh doanh’]
    >> classify(‘Lãi suất từ BIDV rất ưu đãi’, domain=’bank’)[‘INTEREST_RATE’]“`
    8. **Phân tích cảm xúc**“`>>> from underthesea import sentiment
    >>> sentiment(‘hàng kém chất lg,chăn đắp lên dính lông lá khắp người. thất vọng’)negative>>> sentiment(‘Sản phẩm hơi nhỏ so với tưởng tượng nhưng chất lượng tốt, đóng gói cẩn thận.’)positive
    >>> sentiment(‘Đky qua đường link ở bài viết này từ thứ 6 mà giờ chưa thấy ai lhe hết’, domain=’bank’)[‘CUSTOMER_SUPPORT#negative’]>>> sentiment(‘Xem lại vẫn thấy xúc động và tự hào về BIDV của mình’, domain=’bank’)[‘TRADEMARK#positive’]“`
    9. Tài nguyên NLP tiếng Việt
    Danh sách tài nguyên
    “`$ underthesea list-data| Name                | Type        | License | Year | Directory                    ||———————+————-+———+——+——————————|| UIT_ABSA_RESTAURANT | Sentiment   | Open    | 2021 | datasets/UIT_ABSA_RESTAURANT || UIT_ABSA_HOTEL      | Sentiment   | Open    | 2021 | datasets/UIT_ABSA_HOTEL      || SE_Vietnamese-UBS   | Sentiment   | Open    | 2020 | datasets/SE_Vietnamese-UBS   || CP_Vietnamese-UNC   | Plaintext   | Open    | 2020 | datasets/CP_Vietnamese-UNC   || DI_Vietnamese-UVD   | Dictionary  | Open    | 2020 | datasets/DI_Vietnamese-UVD   || UTS2017-BANK        | Categorized | Open    | 2017 | datasets/UTS2017-BANK        || VNTQ_SMALL          | Plaintext   | Open    | 2012 | datasets/LTA                 || VNTQ_BIG            | Plaintext   | Open    | 2012 | datasets/LTA                 || VNESES              | Plaintext   | Open    | 2012 | datasets/LTA                 || VNTC                | Categorized | Open    | 2007 | datasets/VNTC                |
    $ underthesea list-data –all“`
    Download tài nguyên
    “`$ underthesea download-data VNTC100%|██████████| 74846806/74846806 [00:09<00:00, 8243779.16B/s]Resource VNTC is downloaded in ~/.underthesea/datasets/VNTC folder“`
    ### Các tính năng sắp ra mắt– Dịch máy- Chuyển văn bản thành giọng nói- Nhận dạng giọng nói tự động
    ### **Kết bài**
    Với Underthesea, chúng ta có thể dễ dàng cài đặt, sử dụng và tiết kiệm được lượng lớn thời gian thay vì phải gán nhãn bằng tay. Underthesea cũng là thư viện đắc lực hỗ trợ xử lý dữ liệu đầu vào cho rất nhiều bài toán khác. <br>Cảm ơn các bạn đã giành thời gian đọc. <br>Tham khảo: [https://pypi.org/project/underthesea/](https://pypi.org/project/underthesea/)

  • Quản lý python packages như thế nào cho đúng

    Quản lý python packages như thế nào cho đúng

    Maven dùng pom để quản lý packages, Node thì có packages.json. Anh em python thì quản lý python packages bằng pip (Package installer for Python). Tuy nhiên khi sử dụng pip sẽ gặp phải tình huống các dự án khác nhau sử dụng dánh sách packages khác nhau. Vấn đề lớn hơn nữa có thể xảy ra tình huống 2 dự án nào đó sử dụng cùng package ở hai phiên bản khách nhau. Trong bài viết này tôi sẽ hướng dẫn các bạn cách quản lý python packages cho các dự án khác nhau mà không bị phụ thuộc vào nhau. Chúng ta cùng bắt đầu nhé.

    Kiểm tra tình trạng hoạt động của brew nào:

    hieunv@HieuNV ~ % brew update && brew upgrade
    Updated 1 tap (homebrew/core).
    ==> Updated Formulae
    abcm2ps             consul              grails              pjproject
    allure              dps8m               graphicsmagick      rancid
    appstream-glib      erlang              i2p                 ratfor
    byteman             flyway              jruby               stress-ng
    camlp5              folly               libgphoto2          zydis
    cargo-instruments   fonttools           libjwt
    cfengine            gmsh                mill
    clblast             gptfdisk            mongoose
    

    Cài đặt python 3

    brew install python
    

    Mặc định MacOS sử dụng python 2

    hieunv@HieuNV ~ % python -V
    Python 2.7.16
    hieunv@HieuNV ~ % python3 -V
    Python 3.7.0
    

    Các bạn cần thêm đoạn sau vào ~/.zshrc.

    export PATH="/usr/local/opt/python/libexec/bin:/usr/local/sbin:$PATH"
    

    Nếu đang mở Terminal bạn cần đóng Terminal lại rồi kiểm tra lại python version

    hieunv@HieuNV ~ % python -V
    Python 3.7.6
    hieunv@HieuNV ~ % pip -V
    pip 19.3.1 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
    

    Cài đặt virtualenvvirtualenvwrapper

    Với python các packages không được cài đặt cục bộ giống như node. Do đó chúng ta cần tạo ra các môi trường khác nhau với các packages khác nhau để sử dụng cho các dự án khác nhau.

    Cài đặt virtualenv

    pip install virtualenv
    

    Cài đặt virtualenvwrapper

    pip install virtualenvwrapper
    

    Activate virtualenv mỗi khi bật khởi động Terminal

    Các bạn thêm đoạn sau vào ~/.zshrc để virutalenv có thể dượcd khởi động mỗi khi bạn bật Terminal

    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
    

    Tiến hành tạo môi trưởng ảo và cài đặt packages mong muốn

    • Tạo môi trường ảo
    hieunv@HieuNV ~ % mkvirtualenv a
    created virtual environment CPython3.7.6.final.0-64 in 515ms
      creator CPython3Posix(dest=/Users/hieunv/.virtualenvs/a, clear=False, global=False)
      seeder FromAppData(download=False, pip=latest, setuptools=latest, wheel=latest, via=copy, app_data_dir=/Users/hieunv/Library/Application Support/virtualenv/seed-app-data/v1)
      activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
    virtualenvwrapper.user_scripts creating /Users/hieunv/.virtualenvs/a/bin/predeactivate
    virtualenvwrapper.user_scripts creating /Users/hieunv/.virtualenvs/a/bin/postdeactivate
    virtualenvwrapper.user_scripts creating /Users/hieunv/.virtualenvs/a/bin/preactivate
    virtualenvwrapper.user_scripts creating /Users/hieunv/.virtualenvs/a/bin/postactivate
    virtualenvwrapper.user_scripts creating /Users/hieunv/.virtualenvs/a/bin/get_env_details
    (a) hieunv@HieuNV ~ %
    

    Các bạn để ý dòng cuối cùng (a). Sau khi tạo xong thì zsh đã activate vào môi trường ảo.

    • Active vào môi trường ảo nếu môi trường chưa được active thì có thể làm như sau:
    hieunv@HieuNV ~ % workon a
    (a) hieunv@HieuNV ~ %
    
    • Khi muốn thoát khỏi môi trường ảo thì có thể làm như sau:
    (a) hieunv@HieuNV ~ % deactivate
    hieunv@HieuNV ~ %
    
    • Để cài đặt packages thì tiến hành cài đặt bằng pip như bình thường
    pip install boto3
    

    Sử dụng môi trường ảo với python 2

    • Cài đặt python 2
    brew install python2
    
    • Tạo môi trường ảo sử dụng python bằng tham số -p
    mkvirtualenv py2 -p python2
    

    Export package list để install trên máy khác

    (a) hieunv@HieuNV ~ % pip freeze > requirements.txt
    (a) hieunv@HieuNV ~ % cat requirements.txt
    boto3==1.12.11
    botocore==1.15.11
    docutils==0.15.2
    jmespath==0.9.5
    python-dateutil==2.8.1
    s3transfer==0.3.3
    six==1.14.0
    urllib3==1.25.8
    

    Cài đặt packages sử dụng requirements.txt

    pip install -r requirements.txt
    

    Tài liệu tham khảo:

    • https://swapps.com/blog/how-to-configure-virtualenvwrapper-with-python3-in-osx-mojave/