Repository: feast-dev/feast

Issue:
ModuleNotFoundError: No module named 'fcntl'

I pip installed feast and tried feast init my_project

got the following error 
anaconda3\envs\feast_env\lib\site-packages\gunicorn\util.py", line 8, in <module>
    import fcntl
ModuleNotFoundError: No module named 'fcntl'

- Version: 0.34.1
- Platform: windows 10
- Subsystem:

I tried researching on that error it shows 
The fcntl module is not available on Windows. The functionality it exposes does not exist on that platform.

Please help me solve the above issue



Discussion:
Hello, I have encountered the same issue as you. I have noticed that the reason for this error is due to the use of the Gunicorn library in the new version of Feast, which does not support Windows. Therefore, I resolved this issue by downgrade the version of Feast.
`pip install feast==0.31.0`
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/sdk/python/feast/constants.py b/sdk/python/feast/constants.py
--- a/sdk/python/feast/constants.py
+++ b/sdk/python/feast/constants.py
@@ -49,3 +49,6 @@
 
 # Environment variable for feature server docker image tag
 DOCKER_IMAGE_TAG_ENV_NAME: str = "FEAST_SERVER_DOCKER_IMAGE_TAG"
+
+# Default feature server registry ttl (seconds)
+DEFAULT_FEATURE_SERVER_REGISTRY_TTL = 5
diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py
--- a/sdk/python/feast/feature_server.py
+++ b/sdk/python/feast/feature_server.py
@@ -1,10 +1,10 @@
 import json
+import sys
 import threading
 import traceback
 import warnings
 from typing import List, Optional
 
-import gunicorn.app.base
 import pandas as pd
 from dateutil import parser
 from fastapi import FastAPI, HTTPException, Request, Response, status
@@ -15,6 +15,7 @@
 
 import feast
 from feast import proto_json, utils
+from feast.constants import DEFAULT_FEATURE_SERVER_REGISTRY_TTL
 from feast.data_source import PushMode
 from feast.errors import PushSourceNotFoundException
 from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesRequest
@@ -45,7 +46,10 @@ class MaterializeIncrementalRequest(BaseModel):
     feature_views: Optional[List[str]] = None
 
 
-def get_app(store: "feast.FeatureStore", registry_ttl_sec: int = 5):
+def get_app(
+    store: "feast.FeatureStore",
+    registry_ttl_sec: int = DEFAULT_FEATURE_SERVER_REGISTRY_TTL,
+):
     proto_json.patch()
 
     app = FastAPI()
@@ -202,24 +206,27 @@ def materialize_incremental(body=Depends(get_body)):
     return app
 
 
-class FeastServeApplication(gunicorn.app.base.BaseApplication):
-    def __init__(self, store: "feast.FeatureStore", **options):
-        self._app = get_app(
-            store=store,
-            registry_ttl_sec=options.get("registry_ttl_sec", 5),
-        )
-        self._options = options
-        super().__init__()
+if sys.platform != "win32":
+    import gunicorn.app.base
 
-    def load_config(self):
-        for key, value in self._options.items():
-            if key.lower() in self.cfg.settings and value is not None:
-                self.cfg.set(key.lower(), value)
+    class FeastServeApplication(gunicorn.app.base.BaseApplication):
+        def __init__(self, store: "feast.FeatureStore", **options):
+            self._app = get_app(
+                store=store,
+                registry_ttl_sec=options["registry_ttl_sec"],
+            )
+            self._options = options
+            super().__init__()
+
+        def load_config(self):
+            for key, value in self._options.items():
+                if key.lower() in self.cfg.settings and value is not None:
+                    self.cfg.set(key.lower(), value)
 
-        self.cfg.set("worker_class", "uvicorn.workers.UvicornWorker")
+            self.cfg.set("worker_class", "uvicorn.workers.UvicornWorker")
 
-    def load(self):
-        return self._app
+        def load(self):
+            return self._app
 
 
 def start_server(
@@ -229,13 +236,19 @@ def start_server(
     no_access_log: bool,
     workers: int,
     keep_alive_timeout: int,
-    registry_ttl_sec: int = 5,
+    registry_ttl_sec: int,
 ):
-    FeastServeApplication(
-        store=store,
-        bind=f"{host}:{port}",
-        accesslog=None if no_access_log else "-",
-        workers=workers,
-        keepalive=keep_alive_timeout,
-        registry_ttl_sec=registry_ttl_sec,
-    ).run()
+    if sys.platform != "win32":
+        FeastServeApplication(
+            store=store,
+            bind=f"{host}:{port}",
+            accesslog=None if no_access_log else "-",
+            workers=workers,
+            keepalive=keep_alive_timeout,
+            registry_ttl_sec=registry_ttl_sec,
+        ).run()
+    else:
+        import uvicorn
+
+        app = get_app(store, registry_ttl_sec)
+        uvicorn.run(app, host=host, port=port, access_log=(not no_access_log))
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -65,7 +65,7 @@
     "typeguard>=4.0.0",
     "fastapi>=0.68.0",
     "uvicorn[standard]>=0.14.0,<1",
-    "gunicorn",
+    "gunicorn; platform_system != 'Windows'",
     # https://github.com/dask/dask/issues/10996
     "dask>=2021.1.0,<2024.3.0",
     "bowler",  # Needed for automatic repo upgrades


Test patch: