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 fcntl.py
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): pass def lockf(fd, operation, length=0, start=0, whence=0): pass
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:
- https://blog.finxter.com/modulenotfounderror-no-module-named-fcntl-python/
- https://github.com/Pylons/waitress
- https://stackoverflow.com/questions/1422368/fcntl-substitute-on-windows
- https://stackoverflow.com/questions/45228395/error-no-module-named-fcntl
- https://stackoverflow.com/questions/30440559/how-to-perform-file-locking-on-windows-without-installing-a-new-package
- https://portalocker.readthedocs.io/en/latest/