Py2exe: Встройте статические файлы в сам EXE-файл и получите доступ к ним

Я нашел решение добавить файлы в library.zip через: Расширьте py2exe для копирования файлов в zipfile, где pkg_resources может загрузить их.

Я могу получить доступ в свой файл, когда library.zip не, включают exe.

Я добавляю файл: text.txt в каталоге: нечто/медиа в library.zip. И я использую этот код:

import pkg_resources
import zipfile
from cStringIO import StringIO

my_data = pkg_resources.resource_string(__name__,"library.zip")

filezip = StringIO(my_data)
zip = zipfile.ZipFile(filezip)
data = zip.read("foo/media/text.txt")

Я пытаюсь использовать pkg_resources, но я думаю, что не понимаю что-то, потому что я мог открыть непосредственно "library.zip".

Мой вопрос состоит в том, как я могу сделать это, когда library.zip, встраивают в exe?

Наилучшие пожелания

Jean-Michel

10
задан jean-michel 21 December 2009 в 12:39
поделиться

2 ответа

После поиска и нескольких разрывов при атаке на другие проблемы, я нашел ответ, который ясен и лаконичен (для стандартных, в любом случае):

Вызов функции через выражение, тип функции которого имеет языковую связь, отличную от языковой связи типа функции определения вызываемой функции, не определен. [5,2,2/1]

Я все еще утверждаю, что на фундаментальном уровне проблематично использовать текст из стандарта C++ для определения поведения библиотеки C, скомпилированной с компилятором C, и как именно работает эта межязыковая совместимость, очень специфична для реализации; однако это самое близкое, я думаю, что любой стандарт может (в настоящее время) надеяться определить такое взаимодействие.

В частности, это неопределенное поведение (и не использует библиотеку C, так что проблема не возникает):

void call(void (*pf)()) { pf(); } // pf() is the UB
extern "C" void f();
int main() { call(f); }
// though I'm unsure if a diagnostic is required for call(f)

Comeau дает диагностику по вызову (f) (хотя она может сделать это, даже если диагностика не требуется).

Это не неопределенное поведение, и показывает, как включить связь языка в тип указателя функции (который через typedef):

extern "C" typedef void F();
void call(F* pf) { pf(); }
extern "C" void f();
int main() { call(f); }

Или может быть записано:

extern "C" {
typedef void F();
void f();
}
void call(F* pf) { pf(); }
int main() { call(f); }
-121--1458377-

Имеет ли принтер квитанции API, который принимает массив байтов, а не последовательность? Если это так, можно упростить преобразование кода в одну последовательность Юникода в массив байтов, используя кодировку, используемую принтером квитанций.

Кроме того, если требуется преобразовать массив байтов в последовательность, символьные значения которого 1-1 соответствуют значениям байтов, можно использовать кодовую страницу 28591 aka Latin1 aka ISO-8859-1.

То есть, следующий

foreach (byte b in converted) 
    builder.Append((char)b); 

string result = builder.ToString(); 

может быть заменен:

// All three of the following are equivalent
// string result = Encoding.GetEncoding(28591).GetString(converted);
// string result = Encoding.GetEncoding("ISO-8859-1").GetString(converted);
string result = Encoding.GetEncoding("Latin1").GetString(converted);

Latin1 является полезной кодировкой, когда вы хотите кодировать двоичные данные в последовательность, например, для передачи через последовательный порт.

-121--3279220-

Не следует использовать pkg_resources для получения файла library.zip. Его следует использовать для извлечения добавленного ресурса.

Предположим, что у вас есть следующая структура проекта:

setup.py
foo/
    __init__.py
    bar.py
    media/
        image.jpg

Вы бы использовали resource_string (или, предпочтительно, resource_stream) для доступа к image.jpg:

img = pkg_resources.resource_string(__name__, 'media/image.jpg')

Это должно «просто работать». По крайней мере, это произошло, когда я связал свои медиафайлы в EXE. (Извините, я с тех пор покинул компанию, где я использовал py2exe, так что у меня нет рабочего примера, чтобы нарисовать.)

Вы также можете попробовать использовать pkg_resources.resource_filename (), но я не думаю, что это работает под py2exe.

0
ответ дан 4 December 2019 в 01:01
поделиться

Спасибо, но я нашел решение

my_data = pkg_resources.resource_stream("__main__",sys.executable) # get lib.zip file
zip = zipfile.ZipFile(my_data)
data = zip.read("foo/media/doc.pdf") # get my data on lib.zip
file = open(output_name, 'wb')
file.write(data) # write it on a file
file.close()

С уважением

1
ответ дан 4 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: