这段代码大多数时候都会产生WindowsError,很少(就像第一次运行时一样)不会。
""" Running hexlified codes from codefiles module prepared previously """
import tempfile
import subprocess
import threading
import os
import codefiles
if __name__ == '__main__':
for ind, c in enumerate(codefiles.exes):
fn = tempfile.mktemp() + '.exe'
# for some reason hexlified code is sometimes odd length and one nibble
if len(c) & 1:
c += '0'
c = c.decode('hex')
with open(fn, 'wb') as f:
f.write(c)
threading.Thread(target=lambda:subprocess.Popen("", executable=fn)).start()
""" One time works, one time WindowsError 32
>>>
132096 c:docume~1adminlocals~1temptmpkhhxxo.exe
991232 c:docume~1adminlocals~1temptmp9ow6zz.exe
>>> ================================ RESTART ================================
>>>
132096 c:docume~1adminlocals~1temptmp3hb0cf.exe
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:Python27libthreading.py", line 810, in __bootstrap_inner
self.run()
File "C:Python27libthreading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:Documents and SettingsAdminMy DocumentsGoogle DrivePythonToolsrunner.pyw", line 18, in <lambda>
threading.Thread(target=lambda:subprocess.Popen("", executable=fn)).start()
File "C:Python27libsubprocess.py", line 710, in __init__
errread, errwrite)
File "C:Python27libsubprocess.py", line 958, in _execute_child
startupinfo)
WindowsError: [Error 32] The process cannot access the file because it is being used by another process
991232 c:docume~1adminlocals~1temptmpnkfuon.exe
>>>
"""
十六进制是用这个脚本完成的,它有时似乎会产生奇数的半字节,这似乎也很奇怪。
# bootstrapper for running hexlified executables,
# hexlification can be done by running this file directly or calling function make
# running can be done by run function in runner module, which imports the code,
# runs them from temporary files
import os
modulename = 'codefiles.py'
def code_file_names(d='.', ext='.exe'):
return [n for n in os.listdir(d)
if n.lower().endswith(ext)]
def make():
codes = code_file_names(os.curdir)
with open(modulename, 'a') as f:
f.write('exes = (')
hex_codes = [open(n, 'rb').read().encode('hex') for n in codes]
assert all(len(c) & 1 == 0 for c in hex_codes)
print len(hex_codes),map(len, hex_codes)
hex_codes = [repr(c) for c in hex_codes]
f.write(',n'.join(hex_codes))
f.write(')n')
if __name__ == '__main__':
import make_exe
# prepare hexlified exes for exes in directory if codefiles not prepared
if modulename not in os.listdir('.'):
try:
os.remove(modulename)
except:
pass
make()
# prepare script for py2_exe to execute the scripts by run from runner
make_exe.py2_exe('runner.pyw', 'tools/dvd.ico')
在马泰利先生的建议下,我得到了错误消失,但仍然没有预期的结果。
我传入新版本的代码来创建exe文件(如果存在)(在新创建例程中保存文件名)。它在创建文件时启动两个代码(两个十六进制代码),但之后会启动第一个代码的多个副本。
> tempfile.mktemp()
,除了由于其安全问题而被弃用多年之外,仅在程序的单次运行中保证唯一的名称,因为根据 https://docs.python.org/2/library/tempfile.html#tempfile.mktemp,"模块使用一个全局变量来告诉它如何构造一个临时名称"。 因此,在第二次运行时,正如非常明确的错误消息告诉您的那样,"该进程无法访问该文件,因为它正被另一个进程使用"(具体来说,由上一次运行启动的进程,即您无法重写当前正在运行的.exe
某个进程)。
解决方法是确保每次运行都使用自己唯一的临时文件目录。 请参阅 https://docs.python.org/2/library/tempfile.html#tempfile.mkdtemp mkdtemp
。 如何最终清理这些临时目录是一个不同的问题,因为只要任何进程在这样的目录中运行.exe
文件,就无法做到这一点——你可能需要一个单独的"清理脚本",它可以为此目的做任何事情,定期运行(例如在 Unix 中我会使用 cron
)和一个存储库(例如一个小sqlite
数据库, 甚至只是一个文件)来记录在以前的运行中创建的哪些临时目录仍然存在并且需要清除(捕获在它们还无法清理时看到的异常,以便将来重试)。