Android 如何使用Python脚本通过ADB运行sqlite语句,以便从JSON文件填充表?

Android 如何使用Python脚本通过ADB运行sqlite语句,以便从JSON文件填充表?,android,python,shell,sqlite,android-emulator,Android,Python,Shell,Sqlite,Android Emulator,虽然标题可能不是很好,但我认为这种怀疑是正确的。我正在为Android开发,并在我的持久层上使用SQLite。为了进行测试(不是单元测试或仪器测试,只是开发测试,比如打开屏幕并检查一些数据以查看布局),我需要在数据库中填充数据——这是一件非常烦人的事情,因为我需要插入大量数据,我不想用它污染我的代码 我想用一种非常简单的方式来实现这一点,我可以将其重新用于我以后开发的任何应用程序、库或模块,因此我决定使用Android调试桥(ADB)来访问emulator shell,并从那里运行sql脚本来插

虽然标题可能不是很好,但我认为这种怀疑是正确的。我正在为Android开发,并在我的持久层上使用SQLite。为了进行测试(不是单元测试或仪器测试,只是开发测试,比如打开屏幕并检查一些数据以查看布局),我需要在数据库中填充数据——这是一件非常烦人的事情,因为我需要插入大量数据,我不想用它污染我的代码

我想用一种非常简单的方式来实现这一点,我可以将其重新用于我以后开发的任何应用程序、库或模块,因此我决定使用Android调试桥(ADB)来访问emulator 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开始,然后进入emulator的shell,进入sqlite3命令行。当这种情况发生时,我不知道如何使用Python在那里运行命令——也许问题的标题是如何将Python中的命令运行到Android Emulator的shell中p

非常感谢您的帮助



p.S.:我知道有更优雅的方法来实现我想要的,比如切换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

好的,我最终发现您可以在一行中运行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