使用 Python 启动临时 MySQL 服务器
Starting a temporary MySQL server with Python
我想通过Python执行特定版本的mysqld进行单元测试。这个想法是在线程上执行服务器,测试并在完成时终止服务器。 (类似于 testing.mysqld,遗憾的是它不适用于 Windows。)。这是当前代码:
#Create a temporary folder.
base_path = tempfile.mkdtemp()
#Extract the default files
zipfile.ZipFile(r"O:\Tools\mysql\min_mysql.zip").extractall(base_path)
#Setup my_ini file
my_ini_path = os.path.join(base_path, "my.ini").replace("\", "/")
unix_base_path = posixpath.normpath(base_path).replace("\", "/")
with open(my_ini_path, 'r') as my_ini:
filedata = my_ini.read()
filedata = filedata.replace("{{basedir}}", unix_base_path)
with open(my_ini_path, 'w', 0) as my_ini:
my_ini.write(filedata)
#Open mysqld
args = r"O:/Tools/mysql/bin/mysqld.exe --defaults-file=\"%s\"" % (my_ini_path)
args = shlex.split(args)
mysqld_process = subprocess.Popen(args, shell=True)
mysqld_process.wait()
但是如果我通过Python执行它,我得到这个错误:
Could not open required defaults file:
"c:\users\pelfeli1\appdata\local\temp\tmp2vct38\my.ini"
Fatal error in defaults handling. Program aborted
到目前为止,我已经在启动进程之前验证了该文件存在。如果我逐字打印命令并执行它,服务器运行正常。
shell中Popen和just execution似乎有区别。我错过了什么?
嗯,问题出在引号上。刚刚更改了这一行:
args = r"O:/Tools/mysql/bin/mysqld.exe --defaults-file=\"%s\"" % (my_ini_path)
到这一行
args = "O:/Tools/mysql/bin/mysqld.exe --defaults-file=%s" % (my_ini_path)
我仍然不知道为什么这会改变任何东西,因为在这两种情况下打印 args 都会提供有效(并且有效)的命令。
如果你想接受它作为答案,我会在这里复制我的评论:
I don't think this is the problem, but the args
string shouldn't be
defined as raw (with the r). Instead, do this:
'O:/Tools/mysql/bin/mysqld.exe --defaults-file="%s"'
(ie. use single
quotes). Unless you intend to pass the backslashes to the command line
现在,考虑以下两个字符串
"foo\"bar\""
r"foo\"bar\""
不相同。第一个呈现 foo"bar"
,而第二个呈现 foo\"bar\"
.
所以,发生的事情是 shell 将其视为文件名:"c:\users\pelfeli1\appdata\local\temp\tmp2vct38\my.ini"
、包括 引号,因为反引号 ( \
)。你可以这样写:
args = 'O:/Tools/mysql/bin/mysqld.exe --defaults-file="%s"' % (my_ini_path)
只是为了防止 my_ini_path
中的空格,没有问题。
我想通过Python执行特定版本的mysqld进行单元测试。这个想法是在线程上执行服务器,测试并在完成时终止服务器。 (类似于 testing.mysqld,遗憾的是它不适用于 Windows。)。这是当前代码:
#Create a temporary folder.
base_path = tempfile.mkdtemp()
#Extract the default files
zipfile.ZipFile(r"O:\Tools\mysql\min_mysql.zip").extractall(base_path)
#Setup my_ini file
my_ini_path = os.path.join(base_path, "my.ini").replace("\", "/")
unix_base_path = posixpath.normpath(base_path).replace("\", "/")
with open(my_ini_path, 'r') as my_ini:
filedata = my_ini.read()
filedata = filedata.replace("{{basedir}}", unix_base_path)
with open(my_ini_path, 'w', 0) as my_ini:
my_ini.write(filedata)
#Open mysqld
args = r"O:/Tools/mysql/bin/mysqld.exe --defaults-file=\"%s\"" % (my_ini_path)
args = shlex.split(args)
mysqld_process = subprocess.Popen(args, shell=True)
mysqld_process.wait()
但是如果我通过Python执行它,我得到这个错误:
Could not open required defaults file:
"c:\users\pelfeli1\appdata\local\temp\tmp2vct38\my.ini"
Fatal error in defaults handling. Program aborted
到目前为止,我已经在启动进程之前验证了该文件存在。如果我逐字打印命令并执行它,服务器运行正常。
shell中Popen和just execution似乎有区别。我错过了什么?
嗯,问题出在引号上。刚刚更改了这一行:
args = r"O:/Tools/mysql/bin/mysqld.exe --defaults-file=\"%s\"" % (my_ini_path)
到这一行
args = "O:/Tools/mysql/bin/mysqld.exe --defaults-file=%s" % (my_ini_path)
我仍然不知道为什么这会改变任何东西,因为在这两种情况下打印 args 都会提供有效(并且有效)的命令。
如果你想接受它作为答案,我会在这里复制我的评论:
I don't think this is the problem, but the
args
string shouldn't be defined as raw (with the r). Instead, do this:'O:/Tools/mysql/bin/mysqld.exe --defaults-file="%s"'
(ie. use single quotes). Unless you intend to pass the backslashes to the command line
现在,考虑以下两个字符串
"foo\"bar\""
r"foo\"bar\""
不相同。第一个呈现 foo"bar"
,而第二个呈现 foo\"bar\"
.
所以,发生的事情是 shell 将其视为文件名:"c:\users\pelfeli1\appdata\local\temp\tmp2vct38\my.ini"
、包括 引号,因为反引号 ( \
)。你可以这样写:
args = 'O:/Tools/mysql/bin/mysqld.exe --defaults-file="%s"' % (my_ini_path)
只是为了防止 my_ini_path
中的空格,没有问题。