Is There an fcntl Replacement on Windows?

Problem Formulation

Say, you work on a Python project from somebody else who used Linux (e.g., a Django or Flask project) and this project imports the fcntl module from the Python Standard Library. 🐍

When you run the project on Linux everything works fine but if you run the project on Windows, it raises an ImportError or ModuleNotFoundError: No Module Named 'fcntl' because fcntl is not available on Windows.

πŸ‘‰ Recommended Tutorial: ModuleNotFoundError: No Module Named ‘fcntl’ (Python)

πŸ’¬ Question: Is it possible to modify the program so that you can still run it on Windows? In other words, is there a replacement for fcntl on Windows?

Clean Answer

The fcntl module is an interface to the fcntl() and ioctl() Unix routines for file and I/O control on file descriptors. It is super specific for the Unix OS API.

Theoretically, a replacement for fcntl on windows would be win32api calls. However, you’d use them differently and you cannot just import the Windows equivalent in Pyhton and fix the error messages or anything.

If things just would be that simple!

The sophisticated migration approach would analyze all different calls to the fcntl module and find a win32api call equivalent. If it doesn’t exist, you need to find a workaround. You may even find ways to skip the system calls because you may not even need to change file descriptors. In fact, in general it is not possible because some fcntl calls simply have no Windows equivalent.

But in most cases, going through the exercise and finding all usages of fcntl calls and doing some thinking to replace or remove them will do the trick.

For example, say you used the fcntl.lockf() function to do some file locking. You can use Windows functionality to accomplish the same thing without fcntl (e.g., see here). Rinse. Repeat.

Simple but not easy.

Dirty Hack

I found a nice workaround to a subset of these problems here.

The idea is to create a custom fcntl module by placing a file called in your local project that Python can import so the ImportError or ModuleNotFoundError goes away. Now, you add all functions your code needs to the module so everything goes through without error. If the functions are not really needed, you can create dummy functions that return dummy values or None.

Here’s an example that replaces the four functions fcntl(), ioctl(), flock(), and lockf():

def fcntl(fd, op, arg=0):
    return 0
def ioctl(fd, op, arg=0, mutable_flag=True):
    return 0 if mutable_flag else ''
def flock(fd, op):
def lockf(fd, operation, length=0, start=0, whence=0):

Of course, you can replace and modify these functions to your own needs, maybe even replace the functionality with Windows functionality. Or skip some functions if you don’t call them in the code. Or add any functions your code calls but that are not defined here.

⭐ This option is best if you just need to get it running but you cannot (or do not want to) change any line of code in the original project.

Alternative Library ‘waitress’

A Windows alternative to some usages of the Linux fcntl package is the waitress package that you can install using pip install waitress.

pip install waitress

Waitress is a production-quality pure-Python WSGI server with very acceptable performance. It has no dependencies except ones which live in the Python standard library. It runs on CPython on Unix and Windows under Python 3.7+. (PyPI)

Learn more here.

Alternative Package portalocker

It has been pointed out at various places online that you can use the portalocker module instead of fcntl.

Why? Because portalocker works for Unix and Windows API calls — it’s a cross-platform API for flock-style file locking in Python that maps fcntl to win32 API calls.

“Portalocker is a library to provide an easy API to file locking.”

However, fcntl is a bit more powerful so it’s not a perfect solution either.

To install portalocker, simply run:

pip install portalocker

Then import portalocker instead of fcntl and replace the code according to the documentation. Here’s an example use:

import portalocker

lock = portalocker.RedisLock('my_lock_channel_name')

with lock:
    print('do something')

Thanks for reading the whole tutorial! If you want to keep improving your Pyhton skills, feel free to download our Python cheat sheets here:

References used in this article: