Вставьте пользовательский ввод в backend python shell - PullRequest
0 голосов
/ 26 мая 2020

Я работаю над домашним проектом, я пытаюсь создать версию Jupyter для командной строки (я полностью понимаю, как глупо это звучит: «почему бы просто не использовать оболочку Python», это только для весело). Я пытался придумать способ запустить экземпляр Python в фоновом режиме, что позволило бы мне подключить ввод пользователя в эту оболочку. Но я просто не могу найти способ сделать это. Есть ли какой-нибудь разумный способ сделать это?

Спасибо!

РЕДАКТИРОВАТЬ: я рассматриваю что-то вроде Jython , но я бы предпочел сделать это полностью в Python, если возможно.

1 Ответ

1 голос
/ 26 мая 2020

Есть два способа, которые я могу придумать, чтобы сделать это. Первый метод использует exec для выполнения кода ввода пользователем.

while True:
    user_input = input("Python command to execute: ")

    try:
        exec(user_input)
    except Exception as e:
        print("Error thrown.")

Однако это имеет свои ограничения. Вы должны написать собственный код, чтобы отлавливать ошибки, соответствующим образом выдавать ошибки и т. Д. c. Второй метод немного сложнее, но также более обобщен. Вы используете метод all is a file и обрабатываете ввод данных пользователем (будь то через оболочку, веб-сайт или что-то еще) как файл. Затем с этим файлом вы его выполняете. Вы можете всегда оставлять оболочку открытой, проверяя, обновился ли файл перед выполнением:

import hashlib
import runpy
import time

FILE = "./file.py"

def get_file_md5(file_name):
    with open(file_name, "rb") as f:
        return hashlib.md5(f.read()).hexdigest()

md5 = get_file_md5(FILE)
first_run = True

while True:
    current_md5 = get_file_md5(FILE)
    if md5 != current_md5 or first_run:
        first_run = False
        md5 = current_md5

        try:
            runpy.run_path(FILE)
        except Exception as e:
            print("Error", e)
    else:
        time.sleep(1)

Вы можете найти этот ответ, который я дал на другой (неопределенно связанный) вопрос, интересный и использования.


Относительно ниже. Уведомление exec(object[, globals[, locals]]) документация:

Во всех случаях, если опциональные части опущены, код выполняется в текущей области. Если предоставлены только глобальные переменные, это должен быть словарь (а не подкласс словаря), который будет использоваться как для глобальных, так и для локальных переменных.

Итак, вы можете сделать:

exec_globals = {}
exec('a = 10; print(a)', exec_globals)

print("\na in exec_globals: ", 'a' in exec_globals)
print("exec_globals['a'] =", exec_globals['a'])

print("\na in globals(): ", 'a' in globals())
print(a)

Результат будет:

10

a in exec_globals:  True
exec_globals['a'] = 10

a in globals():  False

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    print(a)
NameError: name 'a' is not defined
...