Временный каталог Python для выполнения других процессов?

У меня есть строка исходного кода Java на Python, которую я хочу скомпилировать, выполнить и собрать вывод (stdout и stderr). К сожалению, насколько я могу судить, для javac и java требуются настоящие файлы, поэтому мне нужно создать временный каталог.

Как лучше всего это сделать? Модуль tempfile, по-видимому, ориентирован на создание файлов и каталогов, которые видны только процессу Python. Но в этом случае мне нужно, чтобы Java тоже могла их видеть. Тем не менее, я также хочу, чтобы другие вещи обрабатывались разумно, если это возможно (например, удаление папки после завершения или использование соответствующей системной временной папки)


person Antimony    schedule 05.03.2016    source источник
comment
Использование tempfile.mktemp() просто дает вам строку. Эта строка представляет собой путь, который вы можете использовать для создания файла. Затем вы можете передать этот путь javac и java.   -  person zondo    schedule 05.03.2016
comment
tempfile.mktemp устарел, потому что он не создает файл. Это приводит к опасности состояния гонки, потому что другой процесс может претендовать на то же случайно сгенерированное имя файла, прежде чем вы сможете его создать.   -  person Matti Virkkunen    schedule 05.03.2016


Ответы (2)


tempfile.mkstemp создает файл, который обычно отображается в файловой системе, а также возвращает вам путь. Вы должны иметь возможность использовать это для создания ваших входных и выходных файлов - предполагая, что javac будет атомарно перезаписывать выходной файл, если он существует, не должно быть состояния гонки, если другие процессы в вашей системе не работают неправильно.

person Matti Virkkunen    schedule 05.03.2016
comment
Согласно документации, он помечен как неисполняемый. Смогу ли я по-прежнему выполнять полученный файл класса? - person Antimony; 05.03.2016
comment
Я не думаю, что исполняемый бит имеет значение для файлов .class. Впрочем, бит всегда можно поменять. - person Matti Virkkunen; 05.03.2016

tempfile.NamedTemporaryFile и tempfile.TemporaryDirectory отлично подойдет для ваших целей. Результирующие объекты имеют атрибут .name, предоставляющий видимое имя файловой системы, которое java/javac может нормально обрабатывать, просто убедитесь, что:

  1. Установите suffix соответствующим образом, если компилятор настаивает на том, чтобы файлы назывались с расширением .java.
  2. Всегда вызывайте .flush() в дескрипторе файла перед передачей .name из NamedTemporaryFile внешнему процессу, иначе он может (обычно будет) увидеть неполный файл.

Если вы не хотите, чтобы Python очищал файлы при закрытии объектов, либо передайте delete=False конструктору NamedTemporaryFile, либо используйте функции mkstemp и mkdtemp (которые создают объекты, но не очищают их за вас).

Так, например, вы можете сделать:

# Create temporary directory for source and class files
with tempfile.TemporaryDirectory() as d:

    # Write source code
    srcpath = os.path.join(d.name, "myclass.java")
    with open(srcpath, "w") as srcfile:
        srcfile.write('source code goes here')

    # Compile source code
    subprocess.check_call(['javac', srcpath])

    # Run source code
    # Been a while since I've java-ed; you don't include .java or .class
    # when running, right?
    invokename = os.path.splitext(srcpath)[0]
    subprocess.check_call(['java', invokename])
... with block for TemporaryDirectory done, temp directory cleaned up ...
person ShadowRanger    schedule 05.03.2016
comment
tempfile.TemporaryDirectory не существует в Python 2. Значит, мне нужно использовать mkdtemp? - person Antimony; 05.03.2016
comment
@Antimony: вы можете создать свой собственный TemporaryDirectory из mkdtemp, shutil.rmtree и contextlib.contextmanager; не должен занимать более дюжины строк кода снаружи. Или, знаете, перейти на Python 3. Там полно классных вещей! :-) - person ShadowRanger; 05.03.2016
comment
И на самом деле, если не считать лени и использования contextmanager, это в основном то, как это работает в версии Реализация Python 3. - person ShadowRanger; 05.03.2016