Source code for langchain_experimental.llm_bash.bash
"""Wrapper around subprocess to run commands."""from__future__importannotationsimportplatformimportreimportsubprocessfromtypingimportTYPE_CHECKING,List,Unionfromuuidimportuuid4ifTYPE_CHECKING:importpexpect
[docs]classBashProcess:"""Wrapper for starting subprocesses. Uses the python built-in subprocesses.run() Persistent processes are **not** available on Windows systems, as pexpect makes use of Unix pseudoterminals (ptys). MacOS and Linux are okay. Example: .. code-block:: python from langchain_community.utilities.bash import BashProcess bash = BashProcess( strip_newlines = False, return_err_output = False, persistent = False ) bash.run('echo \'hello world\'') """strip_newlines:bool=False"""Whether or not to run .strip() on the output"""return_err_output:bool=False"""Whether or not to return the output of a failed command, or just the error message and stacktrace"""persistent:bool=False"""Whether or not to spawn a persistent session NOTE: Unavailable for Windows environments"""
[docs]def__init__(self,strip_newlines:bool=False,return_err_output:bool=False,persistent:bool=False,):""" Initializes with default settings """self.strip_newlines=strip_newlinesself.return_err_output=return_err_outputself.prompt=""self.process=Noneifpersistent:self.prompt=str(uuid4())self.process=self._initialize_persistent_process(self,self.prompt)
@staticmethoddef_lazy_import_pexpect()->pexpect:"""Import pexpect only when needed."""ifplatform.system()=="Windows":raiseValueError("Persistent bash processes are not yet supported on Windows.")try:importpexpectexceptImportError:raiseImportError("pexpect required for persistent bash processes."" To install, run `pip install pexpect`.")returnpexpect@staticmethoddef_initialize_persistent_process(self:BashProcess,prompt:str)->pexpect.spawn:# Start bash in a clean environment# Doesn't work on windows""" Initializes a persistent bash setting in a clean environment. NOTE: Unavailable on Windows Args: Prompt(str): the bash command to execute """pexpect=self._lazy_import_pexpect()process=pexpect.spawn("env",["-i","bash","--norc","--noprofile"],encoding="utf-8")# Set the custom promptprocess.sendline("PS1="+prompt)process.expect_exact(prompt,timeout=10)returnprocess
[docs]defrun(self,commands:Union[str,List[str]])->str:""" Run commands in either an existing persistent subprocess or on in a new subprocess environment. Args: commands(List[str]): a list of commands to execute in the session """ifisinstance(commands,str):commands=[commands]commands=";".join(commands)ifself.processisnotNone:returnself._run_persistent(commands,)else:returnself._run(commands)
def_run(self,command:str)->str:""" Runs a command in a subprocess and returns the output. Args: command: The command to run """try:output=subprocess.run(command,shell=True,check=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,).stdout.decode()exceptsubprocess.CalledProcessErroraserror:ifself.return_err_output:returnerror.stdout.decode()returnstr(error)ifself.strip_newlines:output=output.strip()returnoutput
[docs]defprocess_output(self,output:str,command:str)->str:""" Uses regex to remove the command from the output Args: output: a process' output string command: the executed command """pattern=re.escape(command)+r"\s*\n"output=re.sub(pattern,"",output,count=1)returnoutput.strip()
def_run_persistent(self,command:str)->str:""" Runs commands in a persistent environment and returns the output. Args: command: the command to execute """pexpect=self._lazy_import_pexpect()ifself.processisNone:raiseValueError("Process not initialized")self.process.sendline(command)# Clear the output with an empty stringself.process.expect(self.prompt,timeout=10)self.process.sendline("")try:self.process.expect([self.prompt,pexpect.EOF],timeout=10)exceptpexpect.TIMEOUT:returnf"Timeout error while executing command {command}"ifself.process.after==pexpect.EOF:returnf"Exited with error status: {self.process.exitstatus}"output=self.process.beforeoutput=self.process_output(output,command)ifself.strip_newlines:returnoutput.strip()returnoutput