Repository: jina-ai/serve
Pull request: feat: add Python 3.9 support
closes #1253 

Problem statement:
add Python 3.9 support
**Describe the feature**

Jina can not run on Python 3.9. We need community support on this to point out the issues, the out-of-date dependencies on Python 3.9.

**Your proposal**

@alexcg1 as a kick-off, can you add your log here?

---
<!-- Optional, but really help us locate the problem faster -->

**Environment**
<!-- Run `jina --version-full` and copy paste the output here -->

**Screenshots**
<!-- If applicable, add screenshots to help explain your problem. -->

Hints from issue discussion:
https://github.com/jina-ai/jina/issues/1250#issue-739099324
On running `jina hello-world` on jina 0.7.12 on mac. `jina -vf` also fails

```
/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/importer.py:130: UserWarning: theses modules or classes can not be imported ['jina.drivers.evaluate', 'jina.drivers.encode', 'jina.drivers.rank', 'jina.drivers.predict', 'jina.drivers.search', 'jina.drivers.index', 'jina.drivers.cache', 'jina.drivers.multimodal', 'jina.drivers.craft']. You can use `jina check` to list all executors and drivers
  warnings.warn(
/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/importer.py:130: UserWarning: theses modules or classes can not be imported ['jina.executors.crafters.BaseCrafter', 'jina.executors.crafters.BaseSegmenter', 'jina.executors.indexers.cache', 'jina.executors.indexers.keyvalue.BinaryPbIndexer', 'jina.executors.indexers.keyvalue.DataURIPbIndexer', 'jina.executors.indexers.keyvalue.UniquePbIndexer', 'jina.executors.encoders.frameworks.BaseEncoder', 'jina.executors.encoders.frameworks.BaseMindsporeEncoder', 'jina.executors.encoders.frameworks.BaseOnnxEncoder', 'jina.executors.encoders.frameworks.BasePaddleEncoder', 'jina.executors.encoders.frameworks.BaseTFEncoder', 'jina.executors.encoders.frameworks.BaseTorchEncoder', 'jina.executors.encoders.tfserving.BaseEncoder', 'jina.executors.encoders.tfserving.BaseTFServingClientEncoder', 'jina.executors.encoders.tfserving.UnaryTFServingClientEncoder', 'jina.executors.evaluators.rank.recall.BaseRankingEvaluator', 'jina.executors.evaluators.rank.recall.RecallEvaluator', 'jina.executors.encoders.BaseAudioEncoder', 'jina.executors.encoders.BaseEncoder', 'jina.executors.encoders.BaseImageEncoder', 'jina.executors.encoders.BaseNumericEncoder', 'jina.executors.encoders.BaseTextEncoder', 'jina.executors.encoders.BaseVideoEncoder', 'jina.executors.encoders.numeric.BaseNumericEncoder', 'jina.executors.encoders.numeric.TransformEncoder', 'jina.executors.evaluators.rank.BaseRankingEvaluator', 'jina.executors.indexers.BaseVectorIndexer', 'jina.executors.indexers.CompoundIndexer', 'jina.executors.indexers.UniqueVectorIndexer', 'jina.executors.indexers.vector.BaseNumpyIndexer', 'jina.executors.indexers.vector.BaseVectorIndexer', 'jina.executors.indexers.vector.NumpyIndexer', 'jina.executors.evaluators.rank.precision.BaseRankingEvaluator', 'jina.executors.evaluators.rank.precision.PrecisionEvaluator']. You can use `jina check` to list all executors and drivers
  warnings.warn(
/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/importer.py:134: UserWarning: due to the missing dependencies or bad implementations, ['jina.hub.crafters.audio.SlidingWindowAudioSlicer.BaseSegmenter', 'jina.hub.crafters.audio.SlidingWindowAudioSlicer.SlidingWindowAudioSlicer', 'jina.hub.crafters.image.ImageResizer.BaseCrafter', 'jina.hub.crafters.image.ImageResizer.ImageResizer', 'jina.hub.encoders.video.VideoTorchEncoder.BaseTorchEncoder', 'jina.hub.encoders.video.VideoTorchEncoder.BaseVideoEncoder', 'jina.hub.encoders.video.VideoTorchEncoder.VideoTorchEncoder', 'jina.hub.indexers.keyvalue.RedisDBIndexer.BinaryPbIndexer', 'jina.hub.indexers.keyvalue.RedisDBIndexer.RedisDBIndexer', 'jina.hub.encoders.nlp.TransformerTorchEncoder.BaseEncoder', 'jina.hub.encoders.nlp.TransformerTorchEncoder.TransformerTorchEncoder', 'jina.hub.indexers.vector.AnnoyIndexer.AnnoyIndexer', 'jina.hub.indexers.vector.AnnoyIndexer.BaseNumpyIndexer', 'jina.hub.encoders.video.VideoPaddleEncoder.BasePaddleEncoder', 'jina.hub.encoders.video.VideoPaddleEncoder.VideoPaddleEncoder', 'jina.hub.encoders.numeric.FeatureAgglomerationEncoder.FeatureAgglomerationEncoder', 'jina.hub.encoders.numeric.FeatureAgglomerationEncoder.TransformEncoder', 'jina.hub.crafters.audio.AudioNormalizer.AudioNormalizer', 'jina.hub.crafters.audio.AudioNormalizer.BaseCrafter', 'jina.hub.indexers.vector.NGTIndexer.BaseNumpyIndexer', 'jina.hub.indexers.vector.NGTIndexer.NGTIndexer', 'jina.hub.encoders.image.ImageKerasEncoder.BaseTFEncoder', 'jina.hub.encoders.image.ImageKerasEncoder.ImageKerasEncoder', 'jina.hub.evaluators.rank.AveragePrecision.AveragePrecisionEvaluator', 'jina.hub.evaluators.rank.AveragePrecision.BaseRankingEvaluator', 'jina.hub.encoders.image.CustomKerasImageEncoder.BaseTFEncoder', 'jina.hub.encoders.image.CustomKerasImageEncoder.CustomKerasImageEncoder', 'jina.hub.encoders.audio.ChromaPitchEncoder.BaseAudioEncoder', 'jina.hub.encoders.audio.ChromaPitchEncoder.ChromaPitchEncoder', 'jina.hub.encoders.numeric.IncrementalPCAEncoder.IncrementalPCAEncoder', 'jina.hub.encoders.numeric.IncrementalPCAEncoder.TransformEncoder', 'jina.hub.indexers.vector.NmsLibIndexer.BaseNumpyIndexer', 'jina.hub.indexers.vector.NmsLibIndexer.NmsLibIndexer', 'jina.hub.crafters.nlp.TikaExtractor.BaseCrafter', 'jina.hub.crafters.nlp.TikaExtractor.TikaExtractor', 'jina.hub.crafters.image.CenterImageCropper.BaseCrafter', 'jina.hub.crafters.image.CenterImageCropper.CenterImageCropper', 'jina.hub.crafters.audio.AudioSlicer.AudioSlicer', 'jina.hub.crafters.audio.AudioSlicer.BaseSegmenter', 'jina.hub.indexers.vector.FaissIndexer.BaseNumpyIndexer', 'jina.hub.indexers.vector.FaissIndexer.FaissIndexer', 'jina.hub.encoders.image.ImageTorchEncoder.BaseTorchEncoder', 'jina.hub.encoders.image.ImageTorchEncoder.ImageTorchEncoder', 'jina.hub.crafters.audio.AudioReader.AudioReader', 'jina.hub.crafters.audio.AudioReader.BaseCrafter', 'jina.hub.crafters.nlp.JiebaSegmenter.BaseSegmenter', 'jina.hub.crafters.nlp.JiebaSegmenter.JiebaSegmenter', 'jina.hub.evaluators.rank.NdcgEvaluator.BaseRankingEvaluator', 'jina.hub.evaluators.rank.NdcgEvaluator.NDCGEvaluator', 'jina.hub.encoders.image.CustomImageTorchEncoder.BaseTorchEncoder', 'jina.hub.encoders.image.CustomImageTorchEncoder.CustomImageTorchEncoder', 'jina.hub.crafters.image.RandomImageCropper.BaseSegmenter', 'jina.hub.crafters.image.RandomImageCropper.RandomImageCropper', 'jina.hub.encoders.numeric.RandomGaussianEncoder.RandomGaussianEncoder', 'jina.hub.encoders.numeric.RandomGaussianEncoder.TransformEncoder', 'jina.hub.evaluators.rank.f1ScoreEvaluator.BaseRankingEvaluator', 'jina.hub.evaluators.rank.f1ScoreEvaluator.f1ScoreEvaluator', 'jina.hub.crafters.nlp.Sentencizer.BaseSegmenter', 'jina.hub.crafters.nlp.Sentencizer.Sentencizer', 'jina.hub.crafters.image.TorchObjectDetectionSegmenter.BaseSegmenter', 'jina.hub.crafters.image.TorchObjectDetectionSegmenter.TorchObjectDetectionSegmenter', 'jina.hub.encoders.image.BigTransferEncoder.BaseTFEncoder', 'jina.hub.encoders.image.BigTransferEncoder.BigTransferEncoder', 'jina.hub.encoders.numeric.CompressionVaeEncoder.BaseNumericEncoder', 'jina.hub.encoders.numeric.CompressionVaeEncoder.BaseTFEncoder', 'jina.hub.encoders.numeric.CompressionVaeEncoder.CompressionVaeEncoder', 'jina.hub.encoders.nlp.FlairTextEncoder.BaseTorchEncoder', 'jina.hub.encoders.nlp.FlairTextEncoder.FlairTextEncoder', 'jina.hub.crafters.nlp.DeepSegmenter.BaseSegmenter', 'jina.hub.crafters.nlp.DeepSegmenter.DeepSegmenter', 'jina.hub.crafters.numeric.ArrayStringReader.ArrayStringReader', 'jina.hub.crafters.numeric.ArrayStringReader.BaseCrafter', 'jina.hub.crafters.numeric.ArrayBytesReader.ArrayBytesReader', 'jina.hub.crafters.numeric.ArrayBytesReader.BaseCrafter', 'jina.hub.encoders.nlp.UniversalSentenceEncoder.BaseTFEncoder', 'jina.hub.encoders.nlp.UniversalSentenceEncoder.UniversalSentenceEncoder', 'jina.hub.indexers.vector.MilvusIndexer.BaseVectorIndexer', 'jina.hub.indexers.vector.MilvusIndexer.MilvusIndexer', 'jina.hub.crafters.nlp.SlidingWindowSegmenter.BaseSegmenter', 'jina.hub.crafters.nlp.SlidingWindowSegmenter.SlidingWindowSegmenter', 'jina.hub.evaluators.rank.MeanReciprocalRankEvaluator.BaseRankingEvaluator', 'jina.hub.evaluators.rank.MeanReciprocalRankEvaluator.MeanReciprocalRankEvaluator', 'jina.hub.encoders.nlp.FarmTextEncoder.BaseTorchEncoder', 'jina.hub.encoders.nlp.FarmTextEncoder.FarmTextEncoder', 'jina.hub.evaluators.rank.ReciprocalRankEvaluator.BaseRankingEvaluator', 'jina.hub.evaluators.rank.ReciprocalRankEvaluator.ReciprocalRankEvaluator', 'jina.hub.indexers.vector.ScannIndexer.BaseNumpyIndexer', 'jina.hub.indexers.vector.ScannIndexer.ScannIndexer', 'jina.hub.crafters.nlp.PDFExtractorSegmenter.BaseSegmenter', 'jina.hub.crafters.nlp.PDFExtractorSegmenter.PDFExtractorSegmenter', 'jina.hub.encoders.nlp.OneHotTextEncoder.BaseTextEncoder', 'jina.hub.encoders.nlp.OneHotTextEncoder.OneHotTextEncoder', 'jina.hub.encoders.nlp.TextPaddlehubEncoder.BasePaddleEncoder', 'jina.hub.encoders.nlp.TextPaddlehubEncoder.TextPaddlehubEncoder', 'jina.hub.encoders.image.ImagePaddlehubEncoder.BasePaddleEncoder', 'jina.hub.encoders.image.ImagePaddlehubEncoder.ImagePaddlehubEncoder', 'jina.hub.crafters.image.ImageFlipper.BaseCrafter', 'jina.hub.crafters.image.ImageFlipper.ImageFlipper', 'jina.hub.indexers.keyvalue.LevelDBIndexer.BinaryPbIndexer', 'jina.hub.indexers.keyvalue.LevelDBIndexer.LevelDBIndexer', 'jina.hub.encoders.nlp.TransformerTFEncoder.BaseEncoder', 'jina.hub.encoders.nlp.TransformerTFEncoder.TransformerTFEncoder', 'jina.hub.encoders.nlp.VSETextEncoder', 'jina.hub.encoders.numeric.RandomSparseEncoder.RandomSparseEncoder', 'jina.hub.encoders.numeric.RandomSparseEncoder.TransformEncoder', 'jina.hub.crafters.image.ImageNormalizer.BaseCrafter', 'jina.hub.crafters.image.ImageNormalizer.ImageNormalizer', 'jina.hub.encoders.numeric.TSNEEncoder.BaseNumericEncoder', 'jina.hub.encoders.numeric.TSNEEncoder.TSNEEncoder', 'jina.hub.indexers.vector.ZarrIndexer.NumpyIndexer', 'jina.hub.indexers.vector.ZarrIndexer.ZarrIndexer', 'jina.hub.encoders.numeric.FastICAEncoder.FastICAEncoder', 'jina.hub.encoders.numeric.FastICAEncoder.TransformEncoder', 'jina.hub.indexers.keyvalue.MongoDBIndexer.BinaryPbIndexer', 'jina.hub.indexers.keyvalue.MongoDBIndexer.MongoDBIndexer', 'jina.hub.encoders.numeric.BaseNumericEncoder', 'jina.hub.encoders.numeric.TransformEncoder', 'jina.hub.crafters.image.SlidingWindowImageCropper.BaseSegmenter', 'jina.hub.crafters.image.SlidingWindowImageCropper.SlidingWindowImageCropper', 'jina.hub.encoders.image.VSEImageEncoder', 'jina.hub.crafters.image.FiveImageCropper.BaseSegmenter', 'jina.hub.crafters.image.FiveImageCropper.FiveImageCropper', 'jina.hub.indexers.vector.SptagIndexer.BaseNumpyIndexer', 'jina.hub.indexers.vector.SptagIndexer.SptagIndexer', 'jina.hub.encoders.nlp.LaserEncoder.BaseTorchEncoder', 'jina.hub.encoders.nlp.LaserEncoder.LaserEncoder', 'jina.hub.encoders.image.ImageOnnxEncoder.BaseOnnxEncoder', 'jina.hub.encoders.image.ImageOnnxEncoder.ImageOnnxEncoder', 'jina.hub.crafters.image.ImageCropper.BaseCrafter', 'jina.hub.crafters.image.ImageCropper.ImageCropper', 'jina.hub.crafters.audio.AudioMonophoner.AudioMonophoner', 'jina.hub.crafters.audio.AudioMonophoner.BaseCrafter', 'jina.hub.crafters.image.ImageReader.BaseCrafter', 'jina.hub.crafters.image.ImageReader.ImageReader', 'jina.hub.encoders.audio.MFCCTimbreEncoder.BaseAudioEncoder', 'jina.hub.encoders.audio.MFCCTimbreEncoder.ChromaPitchEncoder', 'jina.hub.encoders.audio.MFCCTimbreEncoder.MFCCTimbreEncoder', 'jina.hub.encoders.audio.Wav2VecSpeechEncoder.BaseAudioEncoder', 'jina.hub.encoders.audio.Wav2VecSpeechEncoder.BaseTorchEncoder', 'jina.hub.encoders.audio.Wav2VecSpeechEncoder.Wav2VecSpeechEncoder'] can not be imported if you are using these executors/drivers, they wont work. You can use `jina check` to list all executors and drivers
  warnings.warn(
Traceback (most recent call last):
  File "/opt/miniconda3/envs/test/bin/jina", line 8, in <module>
    sys.exit(main())
  File "/opt/miniconda3/envs/test/lib/python3.9/site-packages/cli/__init__.py", line 88, in main
    args = _get_run_args()
  File "/opt/miniconda3/envs/test/lib/python3.9/site-packages/cli/__init__.py", line 8, in _get_run_args
    from jina.logging import default_logger
  File "/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/__init__.py", line 148, in <module>
    from jina.types.request import Request
  File "/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/types/request/__init__.py", line 3, in <module>
    from ..sets import QueryLangSet, DocumentSet
  File "/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/types/sets/__init__.py", line 4, in <module>
    from .document_set import DocumentSet
  File "/opt/miniconda3/envs/test/lib/python3.9/site-packages/jina/types/sets/document_set.py", line 4, in <module>
    from google.protobuf.pyext._message import RepeatedCompositeContainer
ModuleNotFoundError: No module named 'google.protobuf.pyext._message'
```
This issue is stale because it has been open 20 days with no activity. Remove stale label or comment or this will be closed in 4 days
Hi,

I am working on a PR for this issue.

I have found out the issue why **jina** fails to work on Python 3.9
I have resolved this issue partially on my local machine in a Docker container using the **python:3.9-buster** image, where I successfully get the output for running the command:
**jina -vf**
However, running the command:
**jina hello-world**
results in an error related to **ruamel** package.
I'll be attaching screenshots for execution of both the commands.
I'd appreciate to learn about your thoughts on how I can proceed for solving the error related to **ruamel** package.

**jina -vf** runs successfully now.
![image](https://user-images.githubusercontent.com/34855601/102263523-6fb94d00-3f3a-11eb-98aa-2053ec8fb8d6.png)

**jina hello-world** fails.
![image](https://user-images.githubusercontent.com/34855601/102263616-911a3900-3f3a-11eb-9700-daf0009948e9.png)
![image](https://user-images.githubusercontent.com/34855601/102263627-94adc000-3f3a-11eb-83c2-ceb11149de11.png)

I built protobuf from source for cpp and python to help in resolving the error:
**ModuleNotFoundError: No module named 'google.protobuf.pyext._message'**
This error happens due to lack of official Python 3.9 support for Protobuf python and cpp implementations that work with **PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION**. I built protobuf and protobuf/python for both python and cpp from source using a fix, which helped resolve this issue.
This allows **jina -vf** to run successfully.
To investigate the error encountered while running **jina hello-world**, I went through the code flow for the entire error stack trace. Copy pasting it here for ease of access:
```
Traceback (most recent call last):
  File "/usr/local/bin/jina", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.9/site-packages/cli/__init__.py", line 90, in main
    getattr(api, args.cli.replace('-', '_'))(args)
  File "/usr/local/lib/python3.9/site-packages/cli/api.py", line 76, in hello_world
    hello_world(args)
  File "/usr/local/lib/python3.9/site-packages/jina/helloworld/__init__.py", line 52, in hello_world
    f = Flow.load_config(args.uses_index)
  File "/usr/local/lib/python3.9/site-packages/jina/flow/__init__.py", line 138, in load_config
    return yaml.load(fp)
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/main.py", line 343, in load
    return constructor.get_single_data()
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/constructor.py", line 113, in get_single_data
    return self.construct_document(node)
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/constructor.py", line 118, in construct_document
    data = self.construct_object(node)
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/constructor.py", line 146, in construct_object
    data = self.construct_non_recursive_object(node)
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/constructor.py", line 181, in construct_non_recursive_object
    data = constructor(self, node)
  File "/usr/local/lib/python3.9/site-packages/jina/flow/__init__.py", line 99, in from_yaml
    return cls._get_instance_from_yaml(constructor, node)[0]
  File "/usr/local/lib/python3.9/site-packages/jina/flow/__init__.py", line 150, in _get_instance_from_yaml
    return get_parser(version=data.get('version', None)).parse(data), data
  File "/usr/local/lib/python3.9/site-packages/jina/flow/yaml_parser/v1.py", line 61, in parse
    obj = Flow(*tmp_a, env=envs, **tmp_p)
  File "/usr/local/lib/python3.9/site-packages/jina/flow/__init__.py", line 68, in __init__
    self.logger = JinaLogger(self.__class__.__name__, **vars(self.args))
  File "/usr/local/lib/python3.9/site-packages/jina/logging/logger.py", line 129, in __init__
    self.add_handlers(log_config, **context_vars)
  File "/usr/local/lib/python3.9/site-packages/jina/logging/logger.py", line 161, in add_handlers
    config = yaml.load(fp)
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/main.py", line 343, in load
    return constructor.get_single_data()
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/constructor.py", line 111, in get_single_data
    node = self.composer.get_single_node()
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/composer.py", line 78, in get_single_node
    document = self.compose_document()
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/composer.py", line 101, in compose_document
    node = self.compose_node(None, None)
  File "/usr/local/lib/python3.9/site-packages/ruamel/yaml/composer.py", line 120, in compose_node
    anchor = event.anchor
AttributeError: 'NoneType' object has no attribute 'anchor'
```
This error occurs because of getting the value of **event** variable as **None** and then trying to access **anchor** attribute from a **NoneType** variable.
I will need some help from you guys to understand more about how events are processed through the **ruamel** package in **jina** to work ahead on resolving this.

Also, attaching the github links for exact line numbers in **jina** for easily accessing the codebase for tracing the code flow to understand the error stack:
https://github.com/jina-ai/jina/blob/master/jina/helloworld/__init__.py#L52
https://github.com/jina-ai/jina/blob/master/jina/flow/__init__.py#L140
https://github.com/jina-ai/jina/blob/master/jina/flow/__init__.py#L101
https://github.com/jina-ai/jina/blob/master/jina/flow/__init__.py#L152
https://github.com/jina-ai/jina/blob/master/jina/flow/yaml_parser/v1.py#L61
https://github.com/jina-ai/jina/blob/master/jina/flow/__init__.py#L70
https://github.com/jina-ai/jina/blob/master/jina/logging/logger.py#L129
https://github.com/jina-ai/jina/blob/master/jina/logging/logger.py#L161

**ruamel** related github line number links for the final part of the error stack trace:
https://github.com/pycontribs/ruyaml/blob/master/lib/ruyaml/main.py#L343
https://github.com/pycontribs/ruyaml/blob/master/lib/ruyaml/constructor.py#L127
https://github.com/pycontribs/ruyaml/blob/master/lib/ruyaml/composer.py#L75
https://github.com/pycontribs/ruyaml/blob/master/lib/ruyaml/composer.py#L98
https://github.com/pycontribs/ruyaml/blob/master/lib/ruyaml/composer.py#L117
Hey @gamesterrishi ,

Thank you very much for your collaboration.

We are not doing any special thing in this case, we are trying to load python objects from the file https://github.com/jina-ai/jina/blob/master/jina/resources/logging.default.yml.

I am not sure if there is some syntax here that `ruamel` may not accept for python3.9?
Thanks @JoanFM for your comment. I had a similar initial assumption as you about thinking that ruamel might not be ready for Python 3.9. I investigated it further and checked the codebase to for relevant package wheels to get more idea about supported Python versions:

https://sourceforge.net/projects/ruamel-yaml/
https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree/setup.py

https://www.wheelodex.org/projects/ruamel-yaml/
mentions **ruamel.yaml.clib** as one of the requirements.

**Project: | ruamel.yaml
Version: | 0.16.12
Filename: | ruamel.yaml-0.16.12-py2.py3-none-any.whl
Uploaded: | 2020-09-04 14:26:26 +0000**

**Requires-Dist: | ruamel.yaml.clib (>=0.1.2); platform_python_implementation == "CPython" and python_version < "3.9"**

https://www.wheelodex.org/projects/ruamel-yaml-clib/
shows a Python 3.9 wheel does exist.

**Project:	ruamel.yaml.clib
Version:	0.2.2
Filename:	ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux2014_aarch64.whl
Uploaded: | 2020-11-23 22:02:01 +0000**

So I tried installing this wheel and executed **jina hello-world** again. The error that I was encountering got resolved and it ran properly and printed all the logs too.

However, the only issue which I now face is that I get the following line in the log:
**flow is closed and all resources should be released already, current build level is EMPTY**
instead of getting the usual line:
**flow is closed and all resources should be released already, current build level is 0**

Any help around why the current build could be 0 is highly appreciated. I'll attach log ouput after doing some more investigation.
> Thanks @JoanFM for your comment. I had a similar initial assumption as you about thinking that ruamel might not be ready for Python 3.9. I investigated it further and checked the codebase to for relevant package wheels to get more idea about supported Python versions:
> 
> https://sourceforge.net/projects/ruamel-yaml/
> https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree/setup.py
> 
> https://www.wheelodex.org/projects/ruamel-yaml/
> mentions **ruamel.yaml.clib** as one of the requirements.
> 
> **Project: | ruamel.yaml Version: | 0.16.12 Filename: | ruamel.yaml-0.16.12-py2.py3-none-any.whl Uploaded: | 2020-09-04 14:26:26 +0000**
> 
> **Requires-Dist: | ruamel.yaml.clib (>=0.1.2); platform_python_implementation == "CPython" and python_version < "3.9"**
> 
> https://www.wheelodex.org/projects/ruamel-yaml-clib/
> shows a Python 3.9 wheel does exist.
> 
> **Project: ruamel.yaml.clib Version: 0.2.2 Filename: ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux2014_aarch64.whl Uploaded: | 2020-11-23 22:02:01 +0000**
> 
> So I tried installing this wheel and executed **jina hello-world** again. The error that I was encountering got resolved and it ran properly and printed all the logs too.
> 
> However, the only issue which I now face is that I get the following line in the log:
> **flow is closed and all resources should be released already, current build level is EMPTY**
> instead of getting the usual line:
> **flow is closed and all resources should be released already, current build level is 0**
> 
> Any help around why the current build could be 0 is highly appreciated. I'll attach log ouput after doing some more investigation.

Hey @gamesterrishi 

That is not a problem, EMPTY is the enum name whose value is 0, so no problem about it. I guess some change on how enum values are printed
Hey @gamesterrishi, thanks for solving this. You can look at `FlowBuildLevel` in `enums.py`. I think the solution is ready and you can create a PR.

Commit message: feat: add Python 3.9 support

Patch to review:
diff --git a/.github/badges/python-badge.svg b/.github/badges/python-badge.svg
index 13130f1386bd0..fabbe247e94cc 100644
--- a/.github/badges/python-badge.svg
+++ b/.github/badges/python-badge.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="125" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="125" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="66" height="20" fill="#555"/><rect x="66" width="59" height="20" fill="#099cec"/><rect width="125" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgdmlld0JveD0iMCAwIDI0IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHJvbGU9ImltZyI+PHRpdGxlPlB5dGhvbiBpY29uPC90aXRsZT48cGF0aCBkPSJNMTQuMzEuMThsLjkuMi43My4yNi41OS4zLjQ1LjMyLjM0LjM0LjI1LjM0LjE2LjMzLjEuMy4wNC4yNi4wMi4yLS4wMS4xM1Y4LjVsLS4wNS42My0uMTMuNTUtLjIxLjQ2LS4yNi4zOC0uMy4zMS0uMzMuMjUtLjM1LjE5LS4zNS4xNC0uMzMuMS0uMy4wNy0uMjYuMDQtLjIxLjAySDguODNsLS42OS4wNS0uNTkuMTQtLjUuMjItLjQxLjI3LS4zMy4zMi0uMjcuMzUtLjIuMzYtLjE1LjM3LS4xLjM1LS4wNy4zMi0uMDQuMjctLjAyLjIxdjMuMDZIMy4yM2wtLjIxLS4wMy0uMjgtLjA3LS4zMi0uMTItLjM1LS4xOC0uMzYtLjI2LS4zNi0uMzYtLjM1LS40Ni0uMzItLjU5LS4yOC0uNzMtLjIxLS44OC0uMTQtMS4wNUwwIDExLjk3bC4wNi0xLjIyLjE2LTEuMDQuMjQtLjg3LjMyLS43MS4zNi0uNTcuNC0uNDQuNDItLjMzLjQyLS4yNC40LS4xNi4zNi0uMS4zMi0uMDUuMjQtLjAxaC4xNmwuMDYuMDFoOC4xNnYtLjgzSDYuMjRsLS4wMS0yLjc1LS4wMi0uMzcuMDUtLjM0LjExLS4zMS4xNy0uMjguMjUtLjI2LjMxLS4yMy4zOC0uMi40NC0uMTguNTEtLjE1LjU4LS4xMi42NC0uMS43MS0uMDYuNzctLjA0Ljg0LS4wMiAxLjI3LjA1IDEuMDcuMTN6bS02LjMgMS45OGwtLjIzLjMzLS4wOC40MS4wOC40MS4yMy4zNC4zMy4yMi40MS4wOS40MS0uMDkuMzMtLjIyLjIzLS4zNC4wOC0uNDEtLjA4LS40MS0uMjMtLjMzLS4zMy0uMjItLjQxLS4wOS0uNDEuMDktLjMzLjIyek0yMS4xIDYuMTFsLjI4LjA2LjMyLjEyLjM1LjE4LjM2LjI3LjM2LjM1LjM1LjQ3LjMyLjU5LjI4LjczLjIxLjg4LjE0IDEuMDQuMDUgMS4yMy0uMDYgMS4yMy0uMTYgMS4wNC0uMjQuODYtLjMyLjcxLS4zNi41Ny0uNC40NS0uNDIuMzMtLjQyLjI0LS40LjE2LS4zNi4wOS0uMzIuMDUtLjI0LjAyLS4xNi0uMDFoLTguMjJ2LjgyaDUuODRsLjAxIDIuNzYuMDIuMzYtLjA1LjM0LS4xMS4zMS0uMTcuMjktLjI1LjI1LS4zMS4yNC0uMzguMi0uNDQuMTctLjUxLjE1LS41OC4xMy0uNjQuMDktLjcxLjA3LS43Ny4wNC0uODQuMDEtMS4yNy0uMDQtMS4wNy0uMTQtLjktLjItLjczLS4yNS0uNTktLjMtLjQ1LS4zMy0uMzQtLjM0LS4yNS0uMzQtLjE2LS4zMy0uMS0uMy0uMDQtLjI1LS4wMi0uMi4wMS0uMTN2LTUuMzRsLjA1LS42NC4xMy0uNTQuMjEtLjQ2LjI2LS4zOC4zLS4zMi4zMy0uMjQuMzUtLjIuMzUtLjE0LjMzLS4xLjMtLjA2LjI2LS4wNC4yMS0uMDIuMTMtLjAxaDUuODRsLjY5LS4wNS41OS0uMTQuNS0uMjEuNDEtLjI4LjMzLS4zMi4yNy0uMzUuMi0uMzYuMTUtLjM2LjEtLjM1LjA3LS4zMi4wNC0uMjguMDItLjIxVjYuMDdoMi4wOWwuMTQuMDEuMjEuMDN6bS02LjQ3IDE0LjI1bC0uMjMuMzMtLjA4LjQxLjA4LjQxLjIzLjMzLjMzLjIzLjQxLjA4LjQxLS4wOC4zMy0uMjMuMjMtLjMzLjA4LS40MS0uMDgtLjQxLS4yMy0uMzMtLjMzLS4yMy0uNDEtLjA4LS40MS4wOC0uMzMuMjN6Ii8+PC9zdmc+"/><text x="425" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="390">python</text><text x="425" y="140" transform="scale(.1)" textLength="390">python</text><text x="945" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="490">3.7 | 3.8</text><text x="945" y="140" transform="scale(.1)" textLength="490">3.7 | 3.8</text></g></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="155" height="20" role="img" aria-label="python: 3.7 | 3.8 | 3.9"><title>python: 3.7 | 3.8 | 3.9</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="155" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="66" height="20" fill="#555"/><rect x="66" width="89" height="20" fill="#099cec"/><rect width="155" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHRpdGxlPlB5dGhvbiBpY29uPC90aXRsZT48cGF0aCBkPSJNMTQuMjUuMThsLjkuMi43My4yNi41OS4zLjQ1LjMyLjM0LjM0LjI1LjM0LjE2LjMzLjEuMy4wNC4yNi4wMi4yLS4wMS4xM1Y4LjVsLS4wNS42My0uMTMuNTUtLjIxLjQ2LS4yNi4zOC0uMy4zMS0uMzMuMjUtLjM1LjE5LS4zNS4xNC0uMzMuMS0uMy4wNy0uMjYuMDQtLjIxLjAySDguNzdsLS42OS4wNS0uNTkuMTQtLjUuMjItLjQxLjI3LS4zMy4zMi0uMjcuMzUtLjIuMzYtLjE1LjM3LS4xLjM1LS4wNy4zMi0uMDQuMjctLjAyLjIxdjMuMDZIMy4xN2wtLjIxLS4wMy0uMjgtLjA3LS4zMi0uMTItLjM1LS4xOC0uMzYtLjI2LS4zNi0uMzYtLjM1LS40Ni0uMzItLjU5LS4yOC0uNzMtLjIxLS44OC0uMTQtMS4wNS0uMDUtMS4yMy4wNi0xLjIyLjE2LTEuMDQuMjQtLjg3LjMyLS43MS4zNi0uNTcuNC0uNDQuNDItLjMzLjQyLS4yNC40LS4xNi4zNi0uMS4zMi0uMDUuMjQtLjAxaC4xNmwuMDYuMDFoOC4xNnYtLjgzSDYuMThsLS4wMS0yLjc1LS4wMi0uMzcuMDUtLjM0LjExLS4zMS4xNy0uMjguMjUtLjI2LjMxLS4yMy4zOC0uMi40NC0uMTguNTEtLjE1LjU4LS4xMi42NC0uMS43MS0uMDYuNzctLjA0Ljg0LS4wMiAxLjI3LjA1em0tNi4zIDEuOThsLS4yMy4zMy0uMDguNDEuMDguNDEuMjMuMzQuMzMuMjIuNDEuMDkuNDEtLjA5LjMzLS4yMi4yMy0uMzQuMDgtLjQxLS4wOC0uNDEtLjIzLS4zMy0uMzMtLjIyLS40MS0uMDktLjQxLjA5em0xMy4wOSAzLjk1bC4yOC4wNi4zMi4xMi4zNS4xOC4zNi4yNy4zNi4zNS4zNS40Ny4zMi41OS4yOC43My4yMS44OC4xNCAxLjA0LjA1IDEuMjMtLjA2IDEuMjMtLjE2IDEuMDQtLjI0Ljg2LS4zMi43MS0uMzYuNTctLjQuNDUtLjQyLjMzLS40Mi4yNC0uNC4xNi0uMzYuMDktLjMyLjA1LS4yNC4wMi0uMTYtLjAxaC04LjIydi44Mmg1Ljg0bC4wMSAyLjc2LjAyLjM2LS4wNS4zNC0uMTEuMzEtLjE3LjI5LS4yNS4yNS0uMzEuMjQtLjM4LjItLjQ0LjE3LS41MS4xNS0uNTguMTMtLjY0LjA5LS43MS4wNy0uNzcuMDQtLjg0LjAxLTEuMjctLjA0LTEuMDctLjE0LS45LS4yLS43My0uMjUtLjU5LS4zLS40NS0uMzMtLjM0LS4zNC0uMjUtLjM0LS4xNi0uMzMtLjEtLjMtLjA0LS4yNS0uMDItLjIuMDEtLjEzdi01LjM0bC4wNS0uNjQuMTMtLjU0LjIxLS40Ni4yNi0uMzguMy0uMzIuMzMtLjI0LjM1LS4yLjM1LS4xNC4zMy0uMS4zLS4wNi4yNi0uMDQuMjEtLjAyLjEzLS4wMWg1Ljg0bC42OS0uMDUuNTktLjE0LjUtLjIxLjQxLS4yOC4zMy0uMzIuMjctLjM1LjItLjM2LjE1LS4zNi4xLS4zNS4wNy0uMzIuMDQtLjI4LjAyLS4yMVY2LjA3aDIuMDlsLjE0LjAxem0tNi40NyAxNC4yNWwtLjIzLjMzLS4wOC40MS4wOC40MS4yMy4zMy4zMy4yMy40MS4wOC40MS0uMDguMzMtLjIzLjIzLS4zMy4wOC0uNDEtLjA4LS40MS0uMjMtLjMzLS4zMy0uMjMtLjQxLS4wOC0uNDEuMDh6Ii8+PC9zdmc+"/><text aria-hidden="true" x="425" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="390">python</text><text x="425" y="140" transform="scale(.1)" fill="#fff" textLength="390">python</text><text aria-hidden="true" x="1095" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="790">3.7 | 3.8 | 3.9</text><text x="1095" y="140" transform="scale(.1)" fill="#fff" textLength="790">3.7 | 3.8 | 3.9</text></g></svg>
\ No newline at end of file
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index b6306cde5545f..47a020a71f133 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -98,7 +98,7 @@ jobs:
       fail-fast: false
       matrix:
         tag_stage: ["", "-devel", "-daemon"]
-        tag_pyversion: ["-py37", "-py38"]
+        tag_pyversion: ["-py37", "-py38", "-py39"]
     steps:
       - uses: actions/checkout@v2
         with:
@@ -111,6 +111,8 @@ jobs:
 
           if [[ "${{ matrix.tag_pyversion }}" == "-py38" ]]; then
             echo "PY_VERSION=3.8" >> $GITHUB_ENV
+          elif [[ "${{ matrix.tag_pyversion }}" == "-py39" ]]; then
+            echo "PY_VERSION=3.9" >> $GITHUB_ENV
           else
             echo "PY_VERSION=3.7" >> $GITHUB_ENV
             echo "TAG_ALIAS=jinaai/jina:master${{ matrix.tag_stage }}" >> $GITHUB_ENV
diff --git a/Dockerfiles/debianx.Dockerfile b/Dockerfiles/debianx.Dockerfile
index 17bfc51ab494f..025ca7e63f5f2 100644
--- a/Dockerfiles/debianx.Dockerfile
+++ b/Dockerfiles/debianx.Dockerfile
@@ -10,6 +10,7 @@ ARG PY_VERSION=3.7
 FROM python:${PY_VERSION}-slim AS jina_base
 
 ARG VCS_REF
+ARG PY_VERSION
 ARG BUILD_DATE
 ARG JINA_VERSION
 ARG PIP_TAG
@@ -27,8 +28,8 @@ LABEL org.opencontainers.image.created=${BUILD_DATE} \
       org.opencontainers.image.title="Jina" \
       org.opencontainers.image.description="Jina is the cloud-native neural search solution powered by state-of-the-art AI and deep learning technology"
 
-ENV JINA_BUILD_BASE_DEP="python3-grpcio" \
-    JINA_BUILD_DEVEL_DEP="build-essential gcc libc-dev python3-gevent libmagic1" \
+ENV JINA_COMPILERS="gcc libc-dev make" \
+    JINA_BUILD_DEVEL_DEP="python3-gevent libmagic1" \
     PYTHONPATH=$PYTHONPATH:/usr/lib/python${PY_VERSION}/dist-packages:/usr/local/lib/python${PY_VERSION}/site-packages:/usr/lib/python3/dist-packages:/usr/local/lib/python3/site-packages \
     JINA_VERSION=${JINA_VERSION} \
     JINA_VCS_VERSION=${VCS_REF} \
@@ -39,12 +40,13 @@ ENV JINA_BUILD_BASE_DEP="python3-grpcio" \
 
 COPY . /jina/
 
-RUN apt-get update && apt-get install --no-install-recommends -y ${JINA_BUILD_BASE_DEP} && \
-    apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && \
-    ln -s locale.h /usr/include/xlocale.h && \
+RUN ln -s locale.h /usr/include/xlocale.h && \
+    if [ "${PY_VERSION}" = "3.9" ]; then apt-get update && apt-get install --no-install-recommends -y ${JINA_COMPILERS}; fi && \
     cd /jina && \
     pip install . --compile --extra-index-url ${PIP_EXTRA_INDEX_URL} && \
     if [ -n "${PIP_TAG}" ]; then pip install ".[${PIP_TAG}]" --compile --extra-index-url $PIP_EXTRA_INDEX_URL; fi && \
+    if [ "${PY_VERSION}" = "3.9" ]; then apt-get remove -y --auto-remove ${JINA_COMPILERS}; fi && \
+    apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && \
     rm -rf /tmp/* && rm -rf /jina && rm /usr/include/xlocale.h
 
 ENTRYPOINT ["jina"]
@@ -54,10 +56,12 @@ FROM jina_base AS jina_devel
 COPY . /jina/
 
 RUN apt-get update && apt-get install --no-install-recommends -y ruby-dev build-essential && \
+    if [ "${PY_VERSION}" = "3.9" ]; then apt-get update && apt-get install --no-install-recommends -y ${JINA_COMPILERS}; fi && \
     apt-get install --no-install-recommends -y ${JINA_BUILD_DEVEL_DEP} && \
-    apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && \
     ln -s locale.h /usr/include/xlocale.h && cd /jina && \
     pip install .[devel] --compile --extra-index-url ${PIP_EXTRA_INDEX_URL} && \
+    if [ "${PY_VERSION}" = "3.9" ]; then apt-get remove -y --auto-remove ${JINA_COMPILERS}; fi && \
+    apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && \
     rm -rf /tmp/* && rm -rf /jina && rm /usr/include/xlocale.h
 
 ENTRYPOINT ["jina"]
@@ -66,11 +70,13 @@ FROM jina_base AS jina_daemon
 
 COPY . /jina/
 
-RUN apt-get update && apt-get install --no-install-recommends -y ruby-dev build-essential && \
-    apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && \
+RUN apt-get update && apt-get install --no-install-recommends -y ruby-dev ${JINA_COMPILERS} && \
+    if [ "${PY_VERSION}" = "3.9" ]; then apt-get update && apt-get install --no-install-recommends -y ${JINA_COMPILERS}; fi && \
     gem install fluentd --no-doc && \
     ln -s locale.h /usr/include/xlocale.h && cd /jina && \
     pip install .[daemon] --compile --extra-index-url ${PIP_EXTRA_INDEX_URL} && \
+    if [ "${PY_VERSION}" = "3.9" ]; then apt-get remove -y --auto-remove ruby-dev ${JINA_COMPILERS}; fi && \
+    apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && \
     rm -rf /tmp/* && rm -rf /jina && rm /usr/include/xlocale.h
 
 ENTRYPOINT ["jinad"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 052f71b66f88b..5a7c1a696047c 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ An easier way to build neural search in the cloud
 </p>
 <p align=center>
 <a href="#license"><img src="https://github.com/jina-ai/jina/blob/master/.github/badges/license-badge.svg?raw=true" alt="Jina" title="Jina is licensed under Apache-2.0"></a>
-<a href="https://pypi.org/project/jina/"><img src="https://github.com/jina-ai/jina/blob/master/.github/badges/python-badge.svg?raw=true" alt="Python 3.7 3.8" title="Jina supports Python 3.7 and above"></a>
+<a href="https://pypi.org/project/jina/"><img src="https://github.com/jina-ai/jina/blob/master/.github/badges/python-badge.svg?raw=true" alt="PPython 3.7 3.8 3.9" title="Jina supports Python 3.7 and above"></a>
 <a href="https://pypi.org/project/jina/"><img src="https://img.shields.io/pypi/v/jina?color=%23099cec&amp;label=PyPI&amp;logo=pypi&amp;logoColor=white" alt="PyPI"></a>
 <a href="https://hub.docker.com/r/jinaai/jina/tags"><img src="https://img.shields.io/docker/v/jinaai/jina?color=%23099cec&amp;label=Docker&amp;logo=docker&amp;logoColor=white&amp;sort=semver" alt="Docker Image Version (latest semver)"></a>
 <a href="https://github.com/jina-ai/jina/actions?query=workflow%3ACI"><img src="https://github.com/jina-ai/jina/workflows/CI/badge.svg" alt="CI"></a>
@@ -38,7 +38,7 @@ Jina is a deep learning-powered search framework for building <strong>cross-/mul
 
 ## Installation
 
-| 📦<br><sub><sup>x86/64,arm/v6,v7,[v8 (Apple M1)](https://github.com/jina-ai/jina/issues/1781)</sup></sub> | On Linux/macOS & Python 3.7/3.8 | Docker Users|
+| 📦<br><sub><sup>x86/64,arm/v6,v7,[v8 (Apple M1)](https://github.com/jina-ai/jina/issues/1781)</sup></sub> | On Linux/macOS & Python 3.7/3.8/[3.9]() | Docker Users|
 | --- | --- | --- |
 | Standard | `pip install -U jina` | `docker run jinaai/jina:latest` |
 | <sub>Daemon</sub> | <sub>`pip install -U "jina[daemon]"`</sub> | <sub>`docker run --network=host jinaai/jina:latest-daemon`</sub> |
diff --git a/RELEASE.md b/RELEASE.md
index 0fc72a87b1802..9accb12c22a55 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -68,6 +68,7 @@ jinaai/jina:{version}{python_version}{extra}
 - `{python_version}`: The Python version of the image. Possible values: 
     - ` `, `-py37`: Python 3.7;
     - `-py38` for Python 3.8;
+    - `-py39` for Python 3.9;
 - `{extra}`: the extra dependency installed along with Jina. Possible values:
     - ` `: Jina is installed inside the image via `pip install jina`;
     - `-devel`: Jina is installed inside the image via `pip install jina[devel]`;
diff --git a/docs/chapters/install/os/on-x.md b/docs/chapters/install/os/on-x.md
index 17f1f1b803f06..dd5ba4aeec3c3 100644
--- a/docs/chapters/install/os/on-x.md
+++ b/docs/chapters/install/os/on-x.md
@@ -10,7 +10,7 @@ Yes! Since `0.8.6` Jina runs smoothly on Jupyter Lab/Notebook. For better experi
 
 ## Google Colab
 
-Jina requires Python 3.7 or 3.8. At the time of writing Google Colab runs Python 3.6.7 so Jina can't be installed via `pip`.
+Jina requires Python 3.7/3.8/3.9. At the time of writing Google Colab runs Python 3.6.7 so Jina can't be installed via `pip`.
 
 ## Fedora
 
diff --git a/jina/__init__.py b/jina/__init__.py
index 30c4c609b0a2c..5d293e1243511 100644
--- a/jina/__init__.py
+++ b/jina/__init__.py
@@ -16,8 +16,24 @@
 import sys as _sys
 import types as _types
 
-if _sys.version_info < (3, 7, 0):
-    raise OSError(f'Jina requires Python 3.7 and above, but yours is {_sys.version_info}')
+from google.protobuf.internal import api_implementation as _api_implementation
+
+if _api_implementation._default_implementation_type != 'cpp':
+    import warnings as _warnings
+
+    _warnings.warn('''
+    You are using Python protobuf backend, not the C++ version, which is much faster.
+    
+    This is often due to C++ implementation failed to compile while installing Protobuf
+    - You are using in Python 3.9 (https://github.com/jina-ai/jina/issues/1801)
+    - You are using on architecture other than x86_64/armv6/armv7
+    - You installation is broken, try `pip install --force protobuf`
+    - You have C++ backend but you shut it down, try `export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp`
+    
+    ''', RuntimeWarning)
+
+if _sys.version_info < (3, 7, 0) or _sys.version_info >= (3, 10, 0):
+    raise OSError(f'Jina requires Python 3.7/3.8/3.9, but yours is {_sys.version_info}')
 
 if _sys.version_info >= (3, 8, 0) and _platform.system() == 'Darwin':
     # temporary fix for python 3.8 on macos where the default start is set to "spawn"
diff --git a/jina/types/sets/document.py b/jina/types/sets/document.py
index e592bcd85d841..39d1ea1175d59 100644
--- a/jina/types/sets/document.py
+++ b/jina/types/sets/document.py
@@ -3,7 +3,13 @@
 from typing import Union, Sequence, Iterable, Tuple
 
 import numpy as np
-from google.protobuf.pyext._message import RepeatedCompositeContainer
+
+try:
+    # when protobuf using Cpp backend
+    from google.protobuf.pyext._message import RepeatedCompositeContainer as RepeatedContainer
+except:
+    # when protobuf using Python backend
+    from google.protobuf.internal.containers import RepeatedCompositeFieldContainer as RepeatedContainer
 
 from ...proto.jina_pb2 import DocumentProto
 
@@ -19,7 +25,7 @@ class DocumentSet(MutableSequence):
     a generator but ALSO modify it, count it, get item, or union two 'DocumentSet's using the '+' and '+=' operators.
     """
 
-    def __init__(self, docs_proto: Union['RepeatedCompositeContainer', Sequence['Document']]):
+    def __init__(self, docs_proto: Union['RepeatedContainer', Sequence['Document']]):
         super().__init__()
         self._docs_proto = docs_proto
         self._docs_map = {}
@@ -91,7 +97,7 @@ def clear(self):
 
     def reverse(self):
         """In-place reverse the sequence """
-        if isinstance(self._docs_proto, RepeatedCompositeContainer):
+        if isinstance(self._docs_proto, RepeatedContainer):
             size = len(self._docs_proto)
             hi_idx = size - 1
             for i in range(int(size / 2)):
diff --git a/jina/types/sets/querylang.py b/jina/types/sets/querylang.py
index 34f231911b1d4..2fc87ea4159a8 100644
--- a/jina/types/sets/querylang.py
+++ b/jina/types/sets/querylang.py
@@ -1,7 +1,14 @@
 from collections.abc import MutableSequence
 from typing import Iterable, Union, Dict
 
-from google.protobuf.pyext._message import RepeatedCompositeContainer
+
+try:
+    # when protobuf using Cpp backend
+    from google.protobuf.pyext._message import RepeatedCompositeContainer as RepeatedContainer
+except:
+    # when protobuf using Python backend
+    from google.protobuf.internal.containers import RepeatedCompositeFieldContainer as RepeatedContainer
+
 
 from ..querylang import QueryLang
 from ...helper import typename
@@ -18,7 +25,7 @@ class QueryLangSet(MutableSequence):
     a generator but ALSO modify it, count it, get item.
     """
 
-    def __init__(self, querylang_protos: 'RepeatedCompositeContainer'):
+    def __init__(self, querylang_protos: 'RepeatedContainer'):
         super().__init__()
         self._querylangs_proto = querylang_protos
         self._querylangs_map = {}
diff --git a/setup.py b/setup.py
index 4f33c6c83ee95..d2a4153260d7c 100644
--- a/setup.py
+++ b/setup.py
@@ -8,13 +8,16 @@
 
 PY37 = 'py37'
 PY38 = 'py38'
+PY39 = 'py39'
 
-if sys.version_info >= (3, 8, 0):
+if sys.version_info >= (3, 10, 0) or sys.version_info < (3, 7, 0):
+    raise OSError(f'Jina requires Python 3.7/3.8/3.9, but yours is {sys.version}')
+elif sys.version_info >= (3, 9, 0):
+    py_tag = PY39
+elif sys.version_info >= (3, 8, 0):
     py_tag = PY38
 elif sys.version_info >= (3, 7, 0):
     py_tag = PY37
-else:
-    raise OSError(f'Jina requires Python 3.7 and above, but yours is {sys.version}')
 
 try:
     pkg_name = 'jina'


Code review comments:
diff_hunk: @@ -6,7 +6,7 @@ An easier way to build neural search in the cloud
 </p>
 <p align=center>
 <a href="#license"><img src="https://github.com/jina-ai/jina/blob/master/.github/badges/license-badge.svg?raw=true" alt="Jina" title="Jina is licensed under Apache-2.0"></a>
-<a href="https://pypi.org/project/jina/"><img src="https://github.com/jina-ai/jina/blob/master/.github/badges/python-badge.svg?raw=true" alt="Python 3.7 3.8" title="Jina supports Python 3.7 and above"></a>
+<a href="https://pypi.org/project/jina/"><img src="https://github.com/jina-ai/jina/blob/master/.github/badges/python-badge.svg?raw=true" alt="PPython 3.7 3.8 3.9" title="Jina supports Python 3.7 and above"></a>
path: README.md
text: @user1:
typo?