Python是一种解释性语言。但是为什么我的源目录包含。pyc文件,这些文件被Windows识别为“编译过的Python文件”?
当前回答
我是这么理解的 Python是一种解释性语言…
这个流行的迷因是不正确的,或者,更确切地说,是建立在对(自然)语言水平的误解之上的:类似的错误会说“圣经是一本精装书”。让我来解释一下这个比喻……
"The Bible" is "a book" in the sense of being a class of (actual, physical objects identified as) books; the books identified as "copies of the Bible" are supposed to have something fundamental in common (the contents, although even those can be in different languages, with different acceptable translations, levels of footnotes and other annotations) -- however, those books are perfectly well allowed to differ in a myriad of aspects that are not considered fundamental -- kind of binding, color of binding, font(s) used in the printing, illustrations if any, wide writable margins or not, numbers and kinds of builtin bookmarks, and so on, and so forth.
It's quite possible that a typical printing of the Bible would indeed be in hardcover binding -- after all, it's a book that's typically meant to be read over and over, bookmarked at several places, thumbed through looking for given chapter-and-verse pointers, etc, etc, and a good hardcover binding can make a given copy last longer under such use. However, these are mundane (practical) issues that cannot be used to determine whether a given actual book object is a copy of the Bible or not: paperback printings are perfectly possible!
Similarly, Python is "a language" in the sense of defining a class of language implementations which must all be similar in some fundamental respects (syntax, most semantics except those parts of those where they're explicitly allowed to differ) but are fully allowed to differ in just about every "implementation" detail -- including how they deal with the source files they're given, whether they compile the sources to some lower level forms (and, if so, which form -- and whether they save such compiled forms, to disk or elsewhere), how they execute said forms, and so forth.
The classical implementation, CPython, is often called just "Python" for short -- but it's just one of several production-quality implementations, side by side with Microsoft's IronPython (which compiles to CLR codes, i.e., ".NET"), Jython (which compiles to JVM codes), PyPy (which is written in Python itself and can compile to a huge variety of "back-end" forms including "just-in-time" generated machine language). They're all Python (=="implementations of the Python language") just like many superficially different book objects can all be Bibles (=="copies of The Bible").
If you're interested in CPython specifically: it compiles the source files into a Python-specific lower-level form (known as "bytecode"), does so automatically when needed (when there is no bytecode file corresponding to a source file, or the bytecode file is older than the source or compiled by a different Python version), usually saves the bytecode files to disk (to avoid recompiling them in the future). OTOH IronPython will typically compile to CLR codes (saving them to disk or not, depending) and Jython to JVM codes (saving them to disk or not -- it will use the .class extension if it does save them).
这些较低级别的表单然后由适当的“虚拟机”(也称为“解释器”)执行——CPython VM、. net运行时、Java VM(又名JVM)。
因此,在这个意义上(典型的实现是做什么的),Python是一种“解释型语言”,当且仅当c#和Java是:它们都有一个典型的实现策略,首先产生字节码,然后通过VM/解释器执行它。
More likely the focus is on how "heavy", slow, and high-ceremony the compilation process is. CPython is designed to compile as fast as possible, as lightweight as possible, with as little ceremony as feasible -- the compiler does very little error checking and optimization, so it can run fast and in small amounts of memory, which in turns lets it be run automatically and transparently whenever needed, without the user even needing to be aware that there is a compilation going on, most of the time. Java and C# typically accept more work during compilation (and therefore don't perform automatic compilation) in order to check errors more thoroughly and perform more optimizations. It's a continuum of gray scales, not a black or white situation, and it would be utterly arbitrary to put a threshold at some given level and say that only above that level you call it "compilation"!-)
其他回答
这是为初学者准备的,
在运行脚本之前,Python会自动将脚本编译为已编译的代码,即所谓的字节代码。
运行脚本不被认为是导入,也不会创建.pyc。
例如,如果你有一个脚本文件abc.py,它导入了另一个模块xyz.py,当你运行abc.py时,xyz.py, xyz.py。Pyc将被创建,因为xyz被导入,但没有abc。Pyc文件将被创建,因为abc.py没有被导入。
如果你需要为一个未导入的模块创建一个.pyc文件,你可以使用py_compile和compileall模块。
py_compile模块可以手动编译任何模块。一种方法是交互式地使用该模块中的py_compile.compile函数:
>>> import py_compile
>>> py_compile.compile('abc.py')
这将把.pyc写到与abc.py相同的位置(你可以用可选参数cfile重写它)。
您还可以使用compileall模块自动编译一个或多个目录中的所有文件。
python -m compileall
如果省略目录名(本例中的当前目录),模块将编译sys.path上的所有内容
Python的*.py文件只是一个文本文件,您可以在其中编写一些代码行。当你试图使用"python filename。py"来执行这个文件时
该命令调用Python虚拟机。Python虚拟机有两个组件:“编译器”和“解释器”。解释器不能直接读取*.py文件中的文本,因此该文本首先被转换为面向PVM(不是硬件,而是PVM)的字节码。PVM执行这个字节代码。*。Pyc文件也会生成,作为运行它的一部分,它会对shell或其他文件中的文件执行导入操作。
如果这个*。Pyc文件已经生成,那么每次你运行/执行你的*.py文件时,系统直接加载你的*.py文件。pyc文件,不需要任何编译(这将节省一些处理器的机器周期)。
一旦*。生成Pyc文件,不需要*.py文件,除非你编辑它。
它们是由Python解释器在导入.py文件时创建的,它们包含导入模块/程序的“已编译字节码”,其思想是,如果.pyc比相应的.py文件更新,则可以在后续导入时跳过从源代码到字节码的“翻译”(只需完成一次),从而略微加快启动速度。但它仍然是被解释的。
Python(至少是它最常见的实现)遵循将原始源代码编译为字节码的模式,然后在虚拟机上解释字节码。这意味着(同样,最常见的实现)既不是纯解释器也不是纯编译器。
然而,另一方面,编译过程基本上是隐藏的——.pyc文件基本上被视为缓存;它们能加快速度,但你通常根本不需要注意到它们。它在必要时根据文件时间/日期戳自动使它们失效并重新加载(重新编译源代码)。
我所见过的唯一一次问题是,编译后的字节码文件以某种方式获得了未来的时间戳,这意味着它看起来总是比源文件更新。因为它看起来更新,源文件从来没有重新编译过,所以无论你做了什么更改,它们都被忽略了…
tldr;它是从源代码转换而来的代码,python虚拟机将其解释为执行。
自下而上的理解:任何程序的最后阶段都是在硬件/机器上运行/执行程序的指令。下面是执行前的几个阶段:
Executing/running on CPU Converting bytecode to machine code. Machine code is the final stage of conversion. Instructions to be executed on CPU are given in machine code. Machine code can be executed directly by CPU. Converting Bytecode to machine code. Bytecode is a medium stage. It could be skipped for efficiency, but sacrificing portability. Converting Source code to bytecode. Source code is a human readable code. This is what is used when working on IDEs (code editors) such as Pycharm.
现在来看实际的情节。在进行这些阶段的任何一个阶段时,有两种方法:一次性转换[或执行]代码(又名编译)和逐行转换[或执行]代码(又名解释)。
For example, we could compile a source code to bytecode, compile bytecode to machine code, interpret machine code for execution. Some implementations of languages skip stage 3 for efficiency, i.e. compile source code into machine code and then interpret machine code for execution. Some implementations skip all middle steps and interpret the source code directly for execution. Modern languages often involve both compiling an interpreting. JAVA for example, compiles source code to bytecode [that is how JAVA source is stored, as a bytecode, compile bytecode to machine code [using JVM], and interpret machine code for execution. [Thus JVM is implemented differently for different OSs, but the same JAVA source code could be executed on different OS that have JVM installed.] Python for example, compile source code to bytecode [usually found as .pyc files accompanying the .py source codes], compile bytecode to machine code [done by a virtual machine such as PVM and the result is an executable file], interpret the machine code/executable for execution. When can we say that a language is interpreted or compiled? The answer is by looking into the approach used in execution. If it executes the machine code all at once (== compile), then it's a compiled language. On the other hand, if it executes the machine code line-by-line (==interpret) then it's an interpreted language. Therefore, JAVA and Python are interpreted languages. A confusion might occur because of the third stage, that's converting bytecode to machine code. Often this is done using a software called a virtual machine. The confusion occurs because a virtual machine acts like a machine, but it's actually not! Virtual machines are introduced for portability, having a VM on any REAL machine will allow us to execute the same source code. The approach used in most VMs [that's the third stage] is compiling, thus some people would say it's a compiled language. For the importance of VMs, we often say that such languages are both compiled and interpreted.
推荐文章
- 有没有办法在python中做HTTP PUT
- “foo Is None”和“foo == None”之间有什么区别吗?
- 类没有对象成员
- Django模型“没有显式声明app_label”
- 熊猫能自动从CSV文件中读取日期吗?
- 在python中zip的逆函数是什么?
- 有效的方法应用多个过滤器的熊猫数据框架或系列
- 如何检索插入id后插入行在SQLite使用Python?
- 我如何在Django中添加一个CharField占位符?
- 如何在Python中获取当前执行文件的路径?
- 我如何得到“id”后插入到MySQL数据库与Python?
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象
- Python内存泄漏
- 实现嵌套字典的最佳方法是什么?
- 如何在tensorflow中获得当前可用的gpu ?