How to find out the magic number for the .pyc header in Python 3
Python bytecode (.pyc) files have a header that starts with a magic number that changes between Python versions. How can I (programmatically) find out that number for the current Python version in order to generate a valid header? I'm currently hard-coding the one for Python 3.7.1, but that means I now depend on a specific Python version.
This answer does exactly what I want using py_compile.MAGIC
, but that does not seem to exist anymore in Python 3. How can I do the equivalent in Python 3?
Here's an example of what I'm trying to do:
import dis
import marshal
PYC_HEADER = b'x42x0dx0dx0ax00x00x00x00x00x00x00x00x00x00x00x00'
def f():
print('Hello World')
with open('test.pyc', 'wb') as pyc:
pyc.write(PYC_HEADER)
marshal.dump(dis.Bytecode(f).codeobj, pyc)
This should create a file test.pyc
, which can then be run, using the same Python interpreter as the script, and should print "Hello World!". And it does, but only when using Python 3.7. I'm looking for a way that generates the header for whichever version of Python 3 is used to run the script, rather than hard-coding 3.7.
For context:
I'm compiling a simple programming language to different bytecode formats (LLVM, Java bytecode, Web Assembly and now Python bytecode) as part of a planned tutorial series on compiler construction.
I can generate the Python bytecode using the byteasm library, which gives me a function as a result. But in order to write the contents to a .pyc
file, I need a valid header. By hard-coding the header, the code will only work if the people following the tutorial are running the same version of Python 3 as I am (3.7) or they'd have to manually find out the magic number for their version.
python python-3.x pyc
add a comment |
Python bytecode (.pyc) files have a header that starts with a magic number that changes between Python versions. How can I (programmatically) find out that number for the current Python version in order to generate a valid header? I'm currently hard-coding the one for Python 3.7.1, but that means I now depend on a specific Python version.
This answer does exactly what I want using py_compile.MAGIC
, but that does not seem to exist anymore in Python 3. How can I do the equivalent in Python 3?
Here's an example of what I'm trying to do:
import dis
import marshal
PYC_HEADER = b'x42x0dx0dx0ax00x00x00x00x00x00x00x00x00x00x00x00'
def f():
print('Hello World')
with open('test.pyc', 'wb') as pyc:
pyc.write(PYC_HEADER)
marshal.dump(dis.Bytecode(f).codeobj, pyc)
This should create a file test.pyc
, which can then be run, using the same Python interpreter as the script, and should print "Hello World!". And it does, but only when using Python 3.7. I'm looking for a way that generates the header for whichever version of Python 3 is used to run the script, rather than hard-coding 3.7.
For context:
I'm compiling a simple programming language to different bytecode formats (LLVM, Java bytecode, Web Assembly and now Python bytecode) as part of a planned tutorial series on compiler construction.
I can generate the Python bytecode using the byteasm library, which gives me a function as a result. But in order to write the contents to a .pyc
file, I need a valid header. By hard-coding the header, the code will only work if the people following the tutorial are running the same version of Python 3 as I am (3.7) or they'd have to manually find out the magic number for their version.
python python-3.x pyc
add a comment |
Python bytecode (.pyc) files have a header that starts with a magic number that changes between Python versions. How can I (programmatically) find out that number for the current Python version in order to generate a valid header? I'm currently hard-coding the one for Python 3.7.1, but that means I now depend on a specific Python version.
This answer does exactly what I want using py_compile.MAGIC
, but that does not seem to exist anymore in Python 3. How can I do the equivalent in Python 3?
Here's an example of what I'm trying to do:
import dis
import marshal
PYC_HEADER = b'x42x0dx0dx0ax00x00x00x00x00x00x00x00x00x00x00x00'
def f():
print('Hello World')
with open('test.pyc', 'wb') as pyc:
pyc.write(PYC_HEADER)
marshal.dump(dis.Bytecode(f).codeobj, pyc)
This should create a file test.pyc
, which can then be run, using the same Python interpreter as the script, and should print "Hello World!". And it does, but only when using Python 3.7. I'm looking for a way that generates the header for whichever version of Python 3 is used to run the script, rather than hard-coding 3.7.
For context:
I'm compiling a simple programming language to different bytecode formats (LLVM, Java bytecode, Web Assembly and now Python bytecode) as part of a planned tutorial series on compiler construction.
I can generate the Python bytecode using the byteasm library, which gives me a function as a result. But in order to write the contents to a .pyc
file, I need a valid header. By hard-coding the header, the code will only work if the people following the tutorial are running the same version of Python 3 as I am (3.7) or they'd have to manually find out the magic number for their version.
python python-3.x pyc
Python bytecode (.pyc) files have a header that starts with a magic number that changes between Python versions. How can I (programmatically) find out that number for the current Python version in order to generate a valid header? I'm currently hard-coding the one for Python 3.7.1, but that means I now depend on a specific Python version.
This answer does exactly what I want using py_compile.MAGIC
, but that does not seem to exist anymore in Python 3. How can I do the equivalent in Python 3?
Here's an example of what I'm trying to do:
import dis
import marshal
PYC_HEADER = b'x42x0dx0dx0ax00x00x00x00x00x00x00x00x00x00x00x00'
def f():
print('Hello World')
with open('test.pyc', 'wb') as pyc:
pyc.write(PYC_HEADER)
marshal.dump(dis.Bytecode(f).codeobj, pyc)
This should create a file test.pyc
, which can then be run, using the same Python interpreter as the script, and should print "Hello World!". And it does, but only when using Python 3.7. I'm looking for a way that generates the header for whichever version of Python 3 is used to run the script, rather than hard-coding 3.7.
For context:
I'm compiling a simple programming language to different bytecode formats (LLVM, Java bytecode, Web Assembly and now Python bytecode) as part of a planned tutorial series on compiler construction.
I can generate the Python bytecode using the byteasm library, which gives me a function as a result. But in order to write the contents to a .pyc
file, I need a valid header. By hard-coding the header, the code will only work if the people following the tutorial are running the same version of Python 3 as I am (3.7) or they'd have to manually find out the magic number for their version.
python python-3.x pyc
python python-3.x pyc
asked Dec 18 at 12:53
sepp2k
293k38593609
293k38593609
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
As of Python 3.4 there is the importlib.util.MAGIC_NUMBER
in the module importlib
:
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'
Another solution for Python < 3.4 or Python2 is the get_magic
method of the imp
module.
>>> import imp
>>> imp.get_magic().hex()
'420d0d0a'
Note, that while this still works in Python 3.7, it is deprecated since Python 3.4
Thank you, that's exactly what I needed (minus the.hex()
since it should go into the file as bytes, not a hexstring).
– sepp2k
Dec 18 at 13:13
add a comment |
It moved!1
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER
b'3rrn'
New in version 3.4.
Probably simplest to wrap this in a try/except to fall back to py_compile
.
2
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
1
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53833455%2fhow-to-find-out-the-magic-number-for-the-pyc-header-in-python-3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
As of Python 3.4 there is the importlib.util.MAGIC_NUMBER
in the module importlib
:
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'
Another solution for Python < 3.4 or Python2 is the get_magic
method of the imp
module.
>>> import imp
>>> imp.get_magic().hex()
'420d0d0a'
Note, that while this still works in Python 3.7, it is deprecated since Python 3.4
Thank you, that's exactly what I needed (minus the.hex()
since it should go into the file as bytes, not a hexstring).
– sepp2k
Dec 18 at 13:13
add a comment |
As of Python 3.4 there is the importlib.util.MAGIC_NUMBER
in the module importlib
:
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'
Another solution for Python < 3.4 or Python2 is the get_magic
method of the imp
module.
>>> import imp
>>> imp.get_magic().hex()
'420d0d0a'
Note, that while this still works in Python 3.7, it is deprecated since Python 3.4
Thank you, that's exactly what I needed (minus the.hex()
since it should go into the file as bytes, not a hexstring).
– sepp2k
Dec 18 at 13:13
add a comment |
As of Python 3.4 there is the importlib.util.MAGIC_NUMBER
in the module importlib
:
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'
Another solution for Python < 3.4 or Python2 is the get_magic
method of the imp
module.
>>> import imp
>>> imp.get_magic().hex()
'420d0d0a'
Note, that while this still works in Python 3.7, it is deprecated since Python 3.4
As of Python 3.4 there is the importlib.util.MAGIC_NUMBER
in the module importlib
:
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'
Another solution for Python < 3.4 or Python2 is the get_magic
method of the imp
module.
>>> import imp
>>> imp.get_magic().hex()
'420d0d0a'
Note, that while this still works in Python 3.7, it is deprecated since Python 3.4
edited Dec 18 at 13:12
Dan D.
51.8k107999
51.8k107999
answered Dec 18 at 13:04
kalehmann
2,031317
2,031317
Thank you, that's exactly what I needed (minus the.hex()
since it should go into the file as bytes, not a hexstring).
– sepp2k
Dec 18 at 13:13
add a comment |
Thank you, that's exactly what I needed (minus the.hex()
since it should go into the file as bytes, not a hexstring).
– sepp2k
Dec 18 at 13:13
Thank you, that's exactly what I needed (minus the
.hex()
since it should go into the file as bytes, not a hexstring).– sepp2k
Dec 18 at 13:13
Thank you, that's exactly what I needed (minus the
.hex()
since it should go into the file as bytes, not a hexstring).– sepp2k
Dec 18 at 13:13
add a comment |
It moved!1
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER
b'3rrn'
New in version 3.4.
Probably simplest to wrap this in a try/except to fall back to py_compile
.
2
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
1
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
add a comment |
It moved!1
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER
b'3rrn'
New in version 3.4.
Probably simplest to wrap this in a try/except to fall back to py_compile
.
2
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
1
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
add a comment |
It moved!1
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER
b'3rrn'
New in version 3.4.
Probably simplest to wrap this in a try/except to fall back to py_compile
.
It moved!1
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER
b'3rrn'
New in version 3.4.
Probably simplest to wrap this in a try/except to fall back to py_compile
.
edited Dec 18 at 18:27
answered Dec 18 at 13:05
Josh Lee
117k23210241
117k23210241
2
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
1
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
add a comment |
2
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
1
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
2
2
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
I think you mean "try/except" instead of "try/catch" ;)
– LMD
Dec 18 at 18:09
1
1
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
Hah, too much javascript
– Josh Lee
Dec 18 at 18:27
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53833455%2fhow-to-find-out-the-magic-number-for-the-pyc-header-in-python-3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown