Why does Python compile libraries that are used in a script, but not the script being called itself?
For instance,
If there is main.py
and module.py
, and Python is run by doing python main.py
, there will be a compiled file module.pyc
but not one for main. Why?
Edit
Adding bounty. I don't think this has been properly answered.
If the response is potential disk permissions for the directory of main.py
, why does Python compile modules? They are just as likely (if not more likely) to appear in a location where the user does not have write access. Python could compile main
if it is writable, or alternatively in another directory.
If the reason is that benefits will be minimal, consider the situation when the script will be used a large number of times (such as in a CGI application).
A script is a Python file that's intended to be run directly. When you run it, it should do something. This means that scripts will often contain code written outside the scope of any classes or functions. A module is a Python file that's intended to be imported into scripts or other modules.
Compiled bytecode, which is ran through an interpreter because Python is an interpreted language. Python is a compiled language. It just isn't compiled to a language for which a hardware implementation exists; it is executed by a virtual machine.
The most basic and easy way to run a Python script is by using the python command. You need to open a command line and type the word python followed by the path to your script file, like this: python first_script.py Hello World! Then you hit the ENTER button from the keyboard and that's it.
For the most part, Python is an interpreted language and not a compiled one, although compilation is a step. Python code, written in . py file is first compiled to what is called bytecode (discussed in detail further) which is stored with a . pyc or .
Files are compiled upon import. It isn't a security thing. It is simply that if you import it python saves the output. See this post by Fredrik Lundh on Effbot.
>>>import main # main.pyc is created
When running a script python will not use the *.pyc file. If you have some other reason you want your script pre-compiled you can use the compileall
module.
python -m compileall .
python -m compileall --help option --help not recognized usage: python compileall.py [-l] [-f] [-q] [-d destdir] [-x regexp] [directory ...] -l: don't recurse down -f: force rebuild even if timestamps are up-to-date -q: quiet operation -d destdir: purported directory name for error messages if no directory arguments, -l sys.path is assumed -x regexp: skip files matching the regular expression regexp the regexp is searched for in the full path of the file
If the response is potential disk permissions for the directory of
main.py
, why does Python compile modules?
Modules and scripts are treated the same. Importing is what triggers the output to be saved.
If the reason is that benefits will be minimal, consider the situation when the script will be used a large number of times (such as in a CGI application).
Using compileall does not solve this. Scripts executed by python will not use the *.pyc
unless explicitly called. This has negative side effects, well stated by Glenn Maynard in his answer.
The example given of a CGI application should really be addressed by using a technique like FastCGI. If you want to eliminate the overhead of compiling your script you may want eliminate the overhead of starting up python too, not to mention database connection overhead.
A light bootstrap script can be used or even python -c "import script"
, but these have questionable style.
Glenn Maynard provided some inspiration to correct and improve this answer.
Nobody seems to want to say this, but I'm pretty sure the answer is simply: there's no solid reason for this behavior.
All of the reasons given so far are essentially incorrect:
sys.modules
like any other module. Running a main script is nothing more than importing it with a module name of __main__
.Another issue to note: if you run python foo.py
and foo.pyc exists, it will not be used. You have to explicitly say python foo.pyc
. That's a very bad idea: it means Python won't automatically recompile the .pyc file when it's out of sync (due to the .py file changing), so changes to the .py file won't be used until you manually recompile it. It'll also fail outright with a RuntimeError if you upgrade Python and the .pyc file format is no longer compatible, which happens regularly. Normally, this is all handled transparently.
You shouldn't need to move a script to a dummy module and set up a bootstrapping script to trick Python into caching it. That's a hackish workaround.
The only possible (and very unconvincing) reason I can contrive is to avoid your home directory from being cluttered with a bunch of .pyc files. (This isn't a real reason; if that was an actual concern, then .pyc files should be saved as dotfiles.) It's certainly no reason not to even have an option to do this.
Python should definitely be able to cache the main module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With