Вероятно, есть способ использовать обычный старый POSIX sed
в байт-коде, и это сработает, если имена файлов не появятся в коде, кроме поля co_filename
объекта кода.
Однако, если вы хотите более пуленепробиваемое решение, вот как вы можете изменить байт-код и записать его обратно.
#!/usr/bin python
"""
Renames the co_filename object
"""
import glob, re, types
import os.path as osp
from xasm.misc import write_pycfile
from xasm.assemble import Assembler
from xdis.code import iscode
from xdis.load import load_module
from collections import deque
def change_co_filename(code, new_path):
return types.CodeType(
code.co_argcount,
code.co_kwonlyargcount,
code.co_nlocals,
code.co_stacksize,
code.co_flags,
code.co_code,
code.co_consts,
code.co_names,
code.co_varnames,
new_path,
code.co_name,
code.co_firstlineno,
code.co_lnotab,
code.co_freevars,
code.co_cellvars)
def disco_loop(queue, new_path):
new_code = change_co_filename(queue[0], new_path)
while len(queue) > 0:
co = queue.popleft()
for c in co.co_consts:
if iscode(c):
change_co_filename(c, new_path)
queue.append(c)
pass
pass
return new_code
suffix = "cpython-3.7.pyc"
paths = glob.glob(f"*.{suffix}")
# Modify to figure out what prefix to look for
orig_dirname = "/tmp/pip-unpacked-wheel-2b2_9obo/"
new_dirname = "/tmp/"
for path in paths:
assembler = Assembler("3.7")
version, assembler.timestamp, magic_int, code, is_pypy, assembler.size = load_module(path)
new_path = re.sub(orig_dirname, new_dirname, code.co_filename)
queue = deque([code])
new_code = disco_loop(queue, new_path)
assembler.code_list = [new_code]
write_pycfile(path, assembler)
Это зависит от моего xdis
и xasm
программы, работающие с байт-кодом. (Мне только что пришлось модифицировать последний для 3.7, так как объект кода изменился в этой версии)
Если есть интерес к такого рода вещам, я, вероятно, могу модифицировать вышеупомянутое как отдельную подпрограмму и распространять это с xasm.
Если вы хотите узнать, что происходит при записи Python файлов байт-кода, см. ответ здесь