Skip to main content

Command Line

Input

input(prompt): read a line from the user.

Subprocess

Environment Variables

subprocess.run() 默认继承父进程所有环境变量 (VIRTUAL_ENVPATH etc.):

subprocess.run(["bash", "-c", "echo $VIRTUAL_ENV"], capture_output=True, text=True)

通过 env 自定义环境变量:

# 隔离:清空环境
subprocess.run(["bash", "-c", command], env={})

# 自定义环境
env = {
"PATH": "/usr/bin:/bin",
"HOME": os.environ.get("HOME", ""),
}

# 加载 ~/.bashrc(让 alias/function 生效)
env["BASH_ENV"] = str(Path.home() / ".bashrc")

subprocess.run(["bash", "-c", command], env=env)

Non-Interactive Shell

bash -c "command" 是 non-interactive shell, 不加载用户配置文件:

echo $-  # hBc (不含 'i')
Shell 类型加载的配置文件
Interactive login/etc/profile~/.bash_profile~/.bashrc
Interactive non-login~/.bashrc
Non-interactive (-c)
特性Non-Interactive
Alias~/.bashrc 未加载
Function~/.bashrc 未加载
环境变量✅ 从父进程继承

Click

import click

from caesar_encryption import encrypt

@click.command()
@click.option(
'--input_file',
type=click.File('r'),
help='File in which there is the text you want to encrypt/decrypt.'
'If not provided, a prompt will allow you to type the input text.',
)
@click.option(
'--output_file',
type=click.File('w'),
help='File in which the encrypted / decrypted text will be written.'
'If not provided, the output text will just be printed.',
)
@click.option(
'--decrypt/--encrypt',
'-d/-e',
help='Whether you want to encrypt the input text or decrypt it.'
)
@click.option(
'--key',
'-k',
default=1,
help='The numeric key to use for the caesar encryption / decryption.'
)
def caesar(input_file, output_file, decrypt, key):
if input_file:
text = input_file.read()
else:
text = click.prompt('Enter a text', hide_input=not decrypt)
if decrypt:
key = -key
cypherText = encrypt(text, key)
if output_file:
output_file.write(cypherText)
else:
click.echo(cypherText)

if __name__ == '__main__':
caesar()

Progress

import click
import enchant

from tqdm import tqdm

from caesar_encryption import encrypt

@click.command()
@click.option(
'--input_file',
type=click.File('r'),
required=True,
)
@click.option(
'--output_file',
type=click.File('w'),
required=True,
)
def caesar_breaker(input_file, output_file):
cypherText = input_file.read()
english_dictionary = enchant.Dict("en_US")
best_number_of_english_words = 0
for key in tqdm(range(26)):
plaintext = encrypt(cypherText, -key)
number_of_english_words = 0
for word in plaintext.split(' '):
if word and english_dictionary.check(word):
number_of_english_words += 1
if number_of_english_words > best_number_of_english_words:
best_number_of_english_words = number_of_english_words
best_plaintext = plaintext
best_key = key
click.echo(
f'The most likely encryption key is {best_key}. It gives the following plaintext:\n\n'
f'{best_plaintext[:1000]}...'
)
output_file.write(best_plaintext)

if __name__ == '__main__':
caesar_breaker()