iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python中怎么创建一个Shell
  • 808
分享到

Python中怎么创建一个Shell

2023-06-15 17:06:50 808人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

本篇文章给大家分享的是有关python中怎么创建一个shell,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。基础知识让我们从一个类开始。这是一个简单的方法,将其初始化参数保存到

本篇文章给大家分享的是有关python中怎么创建一个shell,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

基础知识

让我们从一个类开始。这是一个简单的方法,将其初始化参数保存到局部变量,然后使用subprocess.run对其自身进行延迟求值并保存结果。

import subprocess  class PipePy:      def __init__(self, *args):          self._args = args          self._result = None      def _evaluate(self):          if self._result is not None:              return          self._result = subprocess.run(self._args,                                        capture_output=True,                                        text=True)       @property      def returncode(self):          self._evaluate()          return self._result.returncode      @property      def stdout(self):          self._evaluate()          return self._result.stdout      def __str__(self):          return self.stdout      @property      def stderr(self):          self._evaluate()          return self._result.stderr

我们让它旋转一下:

ls = PipePy('ls')  ls_l = PipePy('ls', '-l')  print(ls)  # <<< files.txt  # ... main.py  # ... tags  print(ls_l)  # <<< total 16  # ... -rw-r--r-- 1 kbairak kbairak  125 Jan 22 08:53 files.txt  # ... -rw-r--r-- 1 kbairak kbairak 5425 Feb  1 21:54 main.py  # ... -rw-r--r-- 1 kbairak kbairak 1838 Feb  1 21:54 tags

使其看起来更像“命令式”

不用每次我们要自定义命令时都去调用PipePy。

ls_l = PipePy('ls', '-l')  print(ls_l)

相当于

ls = PipePy('ls')  print(ls('-l'))

换句话说,我们要使:

PipePy('ls', '-l')

相当于

PipePy('ls')('-l')

值得庆幸的是,我们的类创建了惰性对象这一事实在很大程度上帮助了我们:

class PipePy:      # __init__, etc      def __call__(self, *args):          args = self._args + args          return self.__class__(*args)  ls = PipePy('ls')  print(ls('-l'))  # <<< total 16  # ... -rw-r--r-- 1 kbairak kbairak  125 Jan 22 08:53 files.txt  # ... -rw-r--r-- 1 kbairak kbairak 5425 Feb  1 21:54 main.py # ... -rw-r--r-- 1 kbairak kbairak 1838 Feb  1 21:54 tags

关键字参数

如果要向ls传递更多参数,则可能会遇到--sort = size。我们可以轻松地执行ls('-l','--sort = size')。我们可以做得更好吗?

 class PipePy:  -    def __init__(self, *args):  +    def __init__(self, *args, **kwargs):           self._args = args  +        self._kwargs = kwargs           self._result = None       def _evaluate(self):           if self._result is not None:               return  -        self._result = subprocess.run(self._args,  +        self._result = subprocess.run(self._convert_args(),                                         capture_output=True,                                         text=True)  +    def _convert_args(self):  +        args = [str(arg) for arg in self._args]  +        for key, value in self._kwargs.items(): +            keykey = key.replace('_', '-')  +            args.append(f"--{key}={value}")  +        return args  -    def __call__(self, *args):  +    def __call__(self, *args, **kwargs):           args = self._args + args  +        kwargs = {**self._kwargs, **kwargs}  -        return self.__class__(*args)  +        return self.__class__(*args, **kwargs)       # returncode, etc

让我们来旋转一下:

print(ls('-l'))  # <<< total 16  # ... -rw-r--r-- 1 kbairak kbairak  125 Jan 22 08:53 files.txt  # ... -rw-r--r-- 1 kbairak kbairak 5425 Feb  1 21:54 main.py  # ... -rw-r--r-- 1 kbairak kbairak 1838 Feb  1 21:54 tags  print(ls('-l', sort="size"))  # <<< total 16  # ... -rw-r--r-- 1 kbairak kbairak 5425 Feb  1 21:54 main.py  # ... -rw-r--r-- 1 kbairak kbairak 1838 Feb  1 21:54 tags  # ... -rw-r--r-- 1 kbairak kbairak  125 Jan 22 08:53 files.txt

Piping

事情开始变得有趣起来。我们的最终目标是能够做到:

ls = PipePy('ls')  grep = PipePy('grep')  print(ls | grep('tags'))  # <<< tags

我们的过程是:

让__init__和__call__方法接受一个仅用于关键字的新_pipe_input关键字参数,该参数将保存在self上。

在评估期间,如果设置了_pipe_input,它将作为输入参数传递给subprocess.run。

重写__or__方法以将左操作数的结果作为pipe输入传递给右操作数。

 class PipePy:  -    def __init__(self, *args, **kwargs):  +    def __init__(self, *args, _pipe_input=None, **kwargs):           self._args = args           self._kwargs = kwargs  +        self._pipe_input = _pipe_input           self._result = None   -    def __call__(self, *args, **kwargs):  +    def __call__(self, *args, _pipe_input=None, **kwargs):           args = self._args + args           kwargs = {**self._kwargs, **kwargs}  -        return self.__class__(*args, **kwargs)  +        return self.__class__(*args, _pipe_input_pipe_input=_pipe_input, **kwargs)       def _evaluate(self):           if self._result is not None:               return           self._result = subprocess.run(self._convert_args(),  +                                      input=self._pipe_input,                                         capture_output=True,                                         text=True)  +    def __or__(left, right):  +        return right(_pipe_input=left.stdout)

让我们尝试一下(从之前稍微修改命令以证明它确实有效):

ls = PipePy('ls')  grep = PipePy('grep') print(ls('-l') | grep('tags'))  # <<< -rw-r--r-- 1 kbairak kbairak 1838 Feb  1 21:54 tags

让我们添加一些简单的东西

真实性:

class PipePy:      # __init__, etc      def __bool__(self):          return self.returncode == 0

现在我们可以作出如下处理:

git = PipePy('git')  grep = PipePy('grep')  if git('branch') | grep('my_feature'):      print("Branch 'my_feature' found")

读取/写入文件:

class PipePy:      # __init__, etc      def __gt__(self, filename):          with open(filename, 'w') as f:              f.write(self.stdout)      def __rshift__(self, filename):          with open(filename, 'a') as f:             f.write(self.stdout)      def __lt__(self, filename):          with open(filename) as f:              return self(_pipe_input=f.read())

现在可以作出如下操作:

ls = PipePy('ls')  grep = PipePy('grep')  cat = PipePy('cat')  ls > 'files.txt'  print(grep('main') < 'files.txt')  # <<< main.py  ls >> 'files.txt'  print(cat('files.txt'))  # <<< files.txt  # ... main.py  # ... tags  # ... files.txt  # ... main.py  # ... tags

迭代

class PipePy:      # __init__, etc      def __iter__(self):          return iter(self.stdout.split())

现在可以作出如下操作:

ls = PipePy('ls')  for name in ls:      print(name.upper())  # <<< FILES.TXT  # ... MAIN.PY # ... TAGS

表格:

class PipePy:      # __init__, etc      def as_table(self):          lines = self.stdout.splitlines()          fields = lines[0].split()          result = []          for line in lines[1:]:              item = {}              for i, value in enumerate(line.split(maxsplit=len(fields) - 1)):                  item[fields[i]] = value              result.append(item)          return result

现在可以作出下面操作:

ps = PipePy('ps')  print(ps)  # <<<     PID TTY          TIME CMD  # ...    4205 pts/4    00:00:00 zsh  # ...   13592 pts/4    00:00:22 ptiPython  # ...   16253 pts/4    00:00:00 ps  ps.as_table()  # <<< [{'PID': '4205', 'TTY': 'pts/4', 'TIME': '00:00:00', 'CMD': 'zsh'},  # ...  {'PID': '13592', 'TTY': 'pts/4', 'TIME': '00:00:22', 'CMD': 'ptipython'},  # ...  {'PID': '16208', 'TTY': 'pts/4', 'TIME': '00:00:00', 'CMD': 'ps'}]

普通bash实用程序:

在子进程中更改工作目录不会影响当前的脚本或python shell。与更改环境变量相同,以下内容不是PipePy的补充,但很不错:

import os  cd = os.chdir  export = os.environ.__setitem__  pwd = PipePy('pwd')  pwd  # <<< /home/kbairak/prog/python/pipepy  cd('..')  pwd  # <<< /home/kbairak/prog/python

使事情看起来更shell-like

如果我在交互式shell中,则希望能够简单地键入ls并完成它。

class PipePy:      # __init__, etc      def __repr__(self):          return self.stdout + self.stderr

交互式shell

>>> ls = PipePy('ls')  >>> ls  files.txt  main.py  tags

我们的实例是惰性的,这意味着如果我们对它们的结果感兴趣,则将对它们进行评估,此后不再进行评估。如果我们只是想确保已执行该操作怎么办?例如,假设我们有以下脚本:

from pipepy import PipePy  tar = PipePy('tar')  tar('-xf', 'some_arcHive.tar')  print("File extracted")

该脚本实际上不会执行任何操作,因为tar调用实际上并未得到评估。我认为一个不错的惯例是,如果不带参数调用__call__强制求值:

 class PipePy:       def __call__(self, *args, _pipe_input=None, **kwargs):           args = self._args + args           kwargs = {**self._kwargs, **kwargs}  -        return self.__class__(*args, _pipe_input_pipe_input=_pipe_input, **kwargs)  +        result = self.__class__(*args, _pipe_input_pipe_input=_pipe_input, **kwargs)  +        if not args and not _pipe_input and not kwargs:  +            result._evaluate()  +        return result

因此在编写脚本时,如果要确保实际上已调用命令,则必须用一对括号来调用它:

 from pipepy import PipePy   tar = PipePy('tar')  -tar('-xf', 'some_archive.tar')  +tar('-xf', 'some_archive.tar')()   print("File extracted")

但是,我们还没有解决问题。考虑一下:

date = PipePy('date')  date  # <<< Mon Feb  1 10:43:08 PM EET 2021  # Wait 5 seconds  date  # <<< Mon Feb  1 10:43:08 PM EET 2021

不好!date没有改变。date对象将其_result保留在内存中。随后的评估实际上不会调用该命令,而只是返回存储的值。

一种解决方案是通过使用空括号来强制创建副本:

date = PipePy('date')  date()  # <<< Mon Feb  1 10:45:09 PM EET 2021  # Wait 5 seconds  date()  # <<< Mon Feb  1 10:45:14 PM EET 2021

另一个解决方案是:由PipePy构造函数返回的实例不应该是惰性的,但由__call__调用返回的实例将是惰性的。

 class PipePy:  -    def __init__(self, *args, _pipe_input=None, **kwargs):  +    def __init__(self, *args, _pipe_input=None, _lazy=False, **kwargs):           self._args = args           self._kwargs = kwargs           self._pipe_input = _pipe_input  +        self._lazy = _lazy           self._result = None       def __call__(self, *args, _pipe_input=None, **kwargs):           args = self._args + args           kwargs = {**self._kwargs, **kwargs}  -        result = self.__class__(*args, _pipe_input_pipe_input=_pipe_input, **kwargs)  +        result = self.__class__(*args, +                                _pipe_input_pipe_input=_pipe_input,  +                                _lazy=True,  +                                **kwargs)          if not args and not _pipe_input and not kwargs:               result._evaluate()           return result       def _evaluate(self):  -        if self._result is not None:  +        if self._result is not None and self._lazy:               return           self._result = subprocess.run(self._convert_args(),                                         input=self._pipe_input,                                         capture_output=True,                                         text=True)

旋转一下:

date = PipePy('date')  date  # <<< Mon Feb  1 10:54:09 PM EET 2021  # Wait 5 seconds  date  # <<< Mon Feb  1 10:54:14 PM EET 2021

并且可以预见的是,使用空调用的返回值将具有之前的行为:

date = PipePy('date') d = date()  d  # <<< Mon Feb  1 10:56:21 PM EET 2021  # Wait 5 seconds  d  # <<< Mon Feb  1 10:56:21 PM EET 2021

没关系 您不会期望d会更新其值。

越来越危险

好吧,ls('-l')不错,但是如果我们像人类一样简单地做ls -l,那就太好了。嗯,我有个主意:

class PipePy:      # __init__, etc      def __sub__(left, right):          return left(f"-{right}")

现在可以作如下操作:

ls = PipePy('ls')  ls - 'l'  # <<< total 16  # ... -rw-r--r-- 1 kbairak kbairak   46 Feb  1 23:04 files.txt  # ... -rw-r--r-- 1 kbairak kbairak 5425 Feb  1 21:54 main.py  # ... -rw-r--r-- 1 kbairak kbairak 1838 Feb  1 21:54 tags

我们还有一步:

l = 'l'  ls -l

现在无济于事:

import string  for char in string.ascii_letters:      if char in locals():          continue     locals()[char] = char  class PipePy:      # __init__, etc

更危险的事情

用locals()给了我一个灵感。为什么我们必须一直实例化PipePy?我们无法在路径中找到所有可执行文件,并根据它们创建PipePy实例吗?我们当然可以!

import os  import stat  for path in os.get_exec_path():      try:          names = os.listdir(path)      except FileNotFoundError:          continue      for name in names:          if name in locals():              continue          if 'x' in stat.filemode(os.lstat(os.path.join(path, name)).st_mode):              locals()[name] = PipePy(name)

因此,现在,将我们拥有的所有内容都放在一个python文件中,并删除脚本(这是实际bash脚本的转录):

from pipepy import mysqladmin, sleep, drush, grep  for i in range(10):      if Mysqladmin('ping',                    host="mysql_drupal7",                    user="user",                    passWord="password"):          break      sleep(1)()  # Remember to actually invoke  if not drush('status', 'bootstrap') | grep('-q', 'Successful'):      drush('-y', 'site-install', 'standard',            db_url="mysql://user:password@mysql_drupal7:3306/drupal",            acount_pass="kbairak")()  # Remember to actually invoke  drush('en', 'tmgmt_ui', 'tmgmt_entity_ui', 'tmgmt_node_ui')()

以上就是Python中怎么创建一个Shell,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网Python频道。

--结束END--

本文标题: Python中怎么创建一个Shell

本文链接: https://www.lsjlt.com/news/281133.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python中怎么创建一个Shell
    本篇文章给大家分享的是有关Python中怎么创建一个Shell,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。基础知识让我们从一个类开始。这是一个简单的方法,将其初始化参数保存到...
    99+
    2023-06-15
  • 使用shell怎么创建一个文件
    本篇文章为大家展示了使用shell怎么创建一个文件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。shell之创建文件夹:[root@vbox-nginx shell_command]#&n...
    99+
    2023-06-09
  • Python中怎么创建一个瀑布图
    这期内容当中小编将会给大家带来有关Python中怎么创建一个瀑布图,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。创建图表首先,执行标准的输入,并确保IPython能显示matplot图。import&nb...
    99+
    2023-06-17
  • Python中怎么创建一个Silverlight控件
    这篇文章给大家介绍Python中怎么创建一个Silverlight控件,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。XAML文件app.xaml< Canvas xmlns="htt...
    99+
    2023-06-17
  • python怎么创建一个元组
    要创建一个元组,可以使用圆括号将元素括起来,并用逗号分隔元素。以下是创建元组的示例代码:```python# 创建一个空元组empt...
    99+
    2023-09-22
    python
  • 怎么在python中创建一个ndarray数组
    怎么在python中创建一个ndarray数组?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面...
    99+
    2023-06-14
  • 怎么在python中创建一个numpy数组
    本篇文章为大家展示了怎么在python中创建一个numpy数组,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python可以做什么Python是一种编程语言,内置了许多有效的工具,Python几乎无...
    99+
    2023-06-14
  • 怎么在Python中创建一个二叉树
    这篇文章将为大家详细讲解有关怎么在Python中创建一个二叉树,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。二叉树节点定义二叉树的节点定义如下:class TreeNode():#...
    99+
    2023-06-14
  • Python 中怎么创建一个只读字典
    Python 中怎么创建一个只读字典,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。我们知道,当我们向字典添加数据的时候:a = {'name'...
    99+
    2023-06-16
  • python怎么创建一个空元组
    要创建一个空元组,可以使用空的圆括号 `()` 或者调用 `tuple()` 函数。下面是两种方法的示例代码: 方法一:使用空的圆括...
    99+
    2023-10-28
    python
  • VB.NET中怎么创建一个类
    VB.NET中怎么创建一个类,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。首先确定组成这个系统的对象,在VB中,我们常常把每个对象的属性和操作组合到一个类里面,...
    99+
    2023-06-17
  • mysql中怎么创建一个表
    在 mysql 中创建表格,使用 create table 语句,语法为:create table table_name (column_name data_type [constrai...
    99+
    2024-04-14
    mysql
  • linux如何创建一个shell脚本
    要创建一个shell脚本,您需要编写一个文本文件,并为其添加一些特定的标记。下面是创建一个简单的shell脚本的步骤:1. 打开一个...
    99+
    2023-09-29
    Linux shell
  • 怎么在python中创建一个操作页面
    这篇文章给大家介绍怎么在python中创建一个操作页面,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。python可以做什么Python是一种编程语言,内置了许多有效的工具,Python几乎无所不能,该语言通俗易懂、容易...
    99+
    2023-06-14
  • Python中怎么创建一个命令行界面
    这篇文章将为大家详细讲解有关Python中怎么创建一个命令行界面,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。通过创建命令行界面(CLI),可以使程序功能强大并具有交互性。CLI允许您接受命...
    99+
    2023-06-16
  • PYTHON中如何创建一个类?
    可以使用 class 关键字来创建一个类: class MyClass: def __init__(self, arg1, arg2): self.arg1 = arg1 self.arg2 = arg2 ...
    99+
    2023-09-05
    python 开发语言
  • C#中怎么创建一个表单
    这期内容当中小编将会给大家带来有关C#中怎么创建一个表单,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C#创建表单这非常简单,只需要创建一个从 System.WinForms.Form 类中衍生出来的类,...
    99+
    2023-06-17
  • C#中怎么创建一个Access表
    本篇文章给大家分享的是有关C#中怎么创建一个Access表,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C#操作Access主要知识点如下:using System....
    99+
    2023-06-18
  • PyQt5中怎么创建一个按钮
    在PyQt5中,可以使用QtWidgets模块中的QPushButton类来创建一个按钮。以下是一个简单的示例代码: import ...
    99+
    2024-03-12
    PyQt5
  • MYSQL中怎么创建一个视图
    MYSQL中怎么创建一个视图,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一. 视图概述视图是一个虚拟表,其内容由查询定义。同真实的表一样...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作