尽管标题可能不是很好,但我认为疑问是合法的。我正在为Android开发,并在持久性层上使用SQLite。为了进行测试(不是单元或仪器测试,只是开发测试,例如打开屏幕并检查一些数据以查看布局,例如(,我需要数据才能在数据库上填充 - 这是非常烦人的事情,因为我需要插入大量数据,而且我不想用这个数据来污染我的代码。
我想以一种非常简单的方式来做我可以重复使用以后开发的任何应用程序,库或模块,因此我决定使用Android Debug Bridge(ADB(来访问模拟器Shell并且,从那里运行SQL脚本以插入我想要的数据 - 从JSON文件中读取。为此,我想到了以下脚本:
import sys
import json
import subprocess
# ADDS ROOT DIR TO PATH
sys.path.insert(0, '..')
COMMANDS = "abd root ; adb remount ; adb shell; sqlite3 {} ; .headers on ; insert into {} ({}) values ({}); exit ;"
ERROR_INVALID_INPUT = "You must specify the TableName and database full path"
def get_columns_and_values(object):
columns = ""
values = ""
for key, value in object.items():
columns += str(key) + ","
values += str(value) + ","
return [columns, values]
def get_table_name():
return sys.argv[1]
def get_database_path():
return sys.argv[2]
def validate_input():
return len(sys.argv) == 3
def run_commands(columns, values):
formatted_commands = COMMANDS.format(
get_database_path(),
get_table_name(),
columns,
values
)
process = subprocess.Popen(formatted_commands.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
if validate_input():
with open(ARG_SAMPLE_JSON_FILE) as json_file:
data = json.load(json_file)
for object in data:
normalizedRow = get_columns_and_values(object)
run_commands(normalizedRow[0], normalizedRow[1])
else:
print ERROR_INVALID_INPUT
问题是:脚本首先访问bash,然后从那里进入模拟器的外壳,只是为了进入sqlite3命令行。当这种情况发生时,我不知道如何使用Python在那里运行命令 - 也许问题标题可能是如何将命令从Python运行到Android模拟器的Shell中?:p
任何帮助都非常感谢。
p.s。:我知道有更多优雅的方法可以实现我想要的东西,例如Switch Dagger2依赖项以提供模拟的数据,但是这需要大量的配置和调试,有时,有时还需要您只想快速开始在屏幕上看到东西。
好吧,我最终弄清楚您可以在一行中运行sqlite命令。下面的脚本完全可以做我想要的:
import sys
import json
import subprocess
# ADDS ROOT DIR TO PATH
sys.path.insert(0, '..')
ARG_SAMPLE_JSON_FILE = "resources/WorkingDays.json"
CMD_SQL_INSERT = "adb shell sqlite3 {} "INSERT INTO {} ({}) VALUES ({})""
CMD_SQL_SELECT = "adb shell sqlite3 {} "SELECT {} FROM {}""
CMD_SQL_DELETE = "adb shell sqlite3 {} "DELETE FROM {}""
ACTION_INSERT = 'INSERT'
ACTION_DELETE = 'DELETE'
ACTION_SELECT = 'SELECT'
ERROR_INVALID_INPUT = "You must specify the table name, database full path and SQL action to be executed"
ERROR_INVALID_ACTION = "Unrecognized actions. Valid actions are: SELECT, DELETE and INSERT"
def get_columns_and_values(object):
columns = ""
values = ""
for key, value in object.items():
columns += str(key) + ","
if is_number(value):
values += str(value) + ","
else:
values += "'" + str(value) + "'" + ","
return [columns[:-1], values[:-1].replace("False", '0').replace("True", '1')]
def is_number(s):
try:
int(s)
return True
except ValueError:
return False
def get_json_file():
return sys.argv[1]
def get_table_name():
return sys.argv[2]
def get_database_path():
return sys.argv[3]
def get_action():
return sys.argv[4]
def validate_input():
return len(sys.argv) == 5
def run_commands(columns, values):
action = get_action()
if action == ACTION_SELECT:
formatted_command = CMD_SQL_SELECT.format(get_database_path(), columns, get_table_name())
elif action == ACTION_DELETE:
formatted_command = CMD_SQL_DELETE.format(get_database_path(), get_table_name())
elif action == ACTION_INSERT:
formatted_command = CMD_SQL_INSERT.format(get_database_path(), get_table_name(), columns, values)
else:
print ERROR_INVALID_ACTION
return
print "Executing command: {}".format(formatted_command)
process = subprocess.Popen(
formatted_command.split(),
stdout=subprocess.PIPE
)
output, error = process.communicate()
formatted_output = "OUTPUT: {}".format(output)
formatted_error = "ERROR: {}".format(error)
print formatted_output, formatted_error
if validate_input():
with open(get_json_file()) as json_file:
data = json.load(json_file)
for object in data:
normalizedRow = get_columns_and_values(object)
run_commands(normalizedRow[0], normalizedRow[1])
else:
print ERROR_INVALID_INPUT