Jupyter 笔记本将 IPython shell 提升到一个新的高度。Jupyter 项目最初是以 IPython 和 IPython 笔记本的形式出现的。它最初是一个专门针对 Python 的交互式 shell 和笔记本环境，后来扩展为不分语言的环境，支持 Julia、Python 和 R 以及其他任何语言。IPython 是一个 Python shell，类似于你在命令行输入 python 或者 python3 时看到的，但它更聪明、更有用。如果你曾经在 Python shell 中输入过多行命令，并且想重复它，你就会理解每次都要一行一行地滚动浏览历史记录的挫败感。有了 IPython，你可以一次滚动浏览整个块，同时还可以逐行浏览和编辑这些块的部分内容。它具有自动补全，并提供上下文感知的建议：它默认会整理输出：它甚至允许你运行 shell 命令：它还提供了一些有用的功能，比如将 ? 添加到对象中，作为运行 help() 的快捷方式，而不会破坏你的流程：如果你使用的是虚拟环境（参见我关于 virtualenvwrapper 的帖子），可以在环境中用 pip 安装：pip install ipython 要在全系统范围内安装，你可以在 Debian、Ubuntu 或树莓派上使用 apt：sudo apt install ipython3 或使用 pip：sudo pip3 install ipython Jupyter 笔记本Jupyter 笔记本将 IPython shell 提升到了一个新的高度。首先，它们是基于浏览器的，而不是基于终端的。要开始使用，请安装 jupyter。如果你使用的是虚拟环境，请在环境中使用 pip 进行安装：pip install jupyter 要在全系统范围内安装，你可以在 Debian、Ubuntu 或树莓派上使用 apt：sudo apt install jupyter-notebook 或使用 pip：sudo pip3 install jupyter 启动笔记本：jupyter notebook 这将在你的浏览器中打开：你可以使用 “New” 下拉菜单创建一个新的 Python 3 笔记本：现在你可以在 In[ ] 字段中编写和执行命令。使用 Enter 在代码块中换行，使用 Shift+Enter 来执行：你可以编辑和重新运行代码块，你可以重新排序、删除，复制/粘贴，等等。你可以以任何顺序运行代码块，但是要注意的是，任何创建的变量的作用域都将根据执行的时间而不是它们在笔记本中出现的顺序。你可以在 “Kernel” 菜单中重启并清除输出或重启并运行所有的代码块。使用 print 函数每次都会输出。但是如果你有一条没有分配的语句，或者最后一条语句没有分配，那么它总是会输出：你甚至可以把 In 和 Out 作为可索引对象：所有的 IPython 功能都可以使用，而且通常也会表现得更漂亮一些：你甚至可以使用 Matplotlib 进行内联绘图：最后，你可以保存你的笔记本，并将其包含在 Git 仓库中，如果你将其推送到 GitHub，它们将作为已完成的笔记本被渲染：输出、图形和所有一切（如 本例）：本文原载于 Ben Nuttall 的 Tooling Tuesday 博客，经许可后重用。via: https://opensource.com/article/21/3/ipython-shell-jupyter-notebooks作者：Ben Nuttall 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
字典数据结构可以帮助你快速访问信息。字典是 Python 编程语言使用的数据结构。一个 Python 字典由多个键值对组成；每个键值对将键映射到其关联的值上。例如你是一名老师，想把学生姓名与成绩对应起来。你可以使用 Python 字典，将学生姓名映射到他们关联的成绩上。此时，键值对中键是姓名，值是对应的成绩。如果你想知道某个学生的考试成绩，你可以从字典中访问。这种快捷查询方式可以为你节省解析整个列表找到学生成绩的时间。本文介绍了如何通过键访问对应的字典值。学习前，请确保你已经安装了 Anaconda 包管理器和 Jupyter 笔记本。1、在 Jupyter 中打开一个新的笔记本首先在 Web 浏览器中打开并运行 Jupyter。然后，转到左上角的 “File”。选择 “New Notebook”，点击 “Python 3”。开始时，新建的笔记本是无标题的，你可以将其重命名为任何名称。我为我的笔记本取名为 “OpenSource.com Data Dictionary Tutorial”。笔记本中标有行号的位置就是你写代码的区域，也是你输入的位置。在 macOS 上，可以同时按 Shift + Return 键得到输出。在创建新的代码区域前，请确保完成上述动作；否则，你写的任何附加代码可能无法运行。2、新建一个键值对在字典中输入你希望访问的键与值。输入前，你需要在字典上下文中定义它们的含义：empty_dictionary = {} grades = { "Kelsey": 87, "Finley": 92 } one_line = {a: 1, b: 2} 这段代码让字典将特定键与其各自的值关联起来。字典按名称存储数据，从而可以更快地查询。3、通过键访问字典值现在你想查询指定的字典值；在上述例子中，字典值指特定学生的成绩。首先，点击 “Insert” 后选择 “Insert Cell Below”。在新单元格中，定义字典中的键与值。然后，告诉字典打印该值的键，找到需要的值。例如，查询名为 Kelsey 的学生的成绩：# 访问字典中的数据 grades = { "Kelsey": 87, "Finley": 92 } print(grades["Kelsey"]) 87 当你查询 Kelsey 的成绩（也就是你想要查询的值）时，如果你用的是 macOS，只需要同时按 Shift+Return 键。你会在单元格下方看到 Kelsey 的成绩。4、更新已有的键当把一位学生的错误成绩添加到字典时，你会怎么办？可以通过更新字典、存储新值来修正这类错误。首先，选择你想更新的那个键。在上述例子中，假设你错误地输入了 Finley 的成绩，那么 Finley 就是你需要更新的键。为了更新 Finley 的成绩，你需要在下方插入新的单元格，然后创建一个新的键值对。同时按 Shift+Return 键打印字典全部信息：grades["Finley"] = 90 print(grades) {'Kelsey': 87; "Finley": 90} 单元格下方输出带有 Finley 更新成绩的字典。5、添加新键假设你得到一位新学生的考试成绩。你可以用新键值对将那名学生的姓名与成绩补充到字典中。插入新的单元格，以键值对形式添加新学生的姓名与成绩。当你完成这些后，同时按 Shift+Return 键打印字典全部信息：grades["Alex"] = 88 print(grades) {'Kelsey': 87, 'Finley': 90, 'Alex': 88} 所有的键值对输出在单元格下方。使用字典请记住，键与值可以是任意数据类型，但它们很少是 扩展数据类型 non-primitive types 。此外，字典不能以指定的顺序存储、组织里面的数据。如果你想要数据有序，最好使用 Python 列表，而非字典。如果你考虑使用字典，首先要确认你的数据结构是否是合适的，例如像电话簿的结构。如果不是，列表、元组、树或者其他数据结构可能是更好的选择。via: https://opensource.com/article/21/3/dictionary-values-python作者：Lauren Maffeo 选题：lujun9972 译者：DCOLIVERSUN 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在 Jupyter 里使用 Python 来分析日历，以了解你是如何使用时间的。Python 在探索数据方面具有令人难以置信的可扩展性。利用 Pandas 或 Dask，你可以将 Jupyter 扩展到大数据领域。但是小数据、个人资料、私人数据呢？JupyterLab 和 Jupyter Notebook 为我提供了一个绝佳的环境，可以让我审视我的笔记本电脑生活。我的探索是基于以下事实：我使用的几乎每个服务都有一个 Web API。我使用了诸多此类服务：待办事项列表、时间跟踪器、习惯跟踪器等。还有一个几乎每个人都会使用到：日历。相同的思路也可以应用于其他服务，但是日历具有一个很酷的功能：几乎所有 Web 日历都支持的开放标准 —— CalDAV。在 Jupyter 中使用 Python 解析日历大多数日历提供了导出为 CalDAV 格式的方法。你可能需要某种身份验证才能访问这些私有数据。按照你的服务说明进行操作即可。如何获得凭据取决于你的服务，但是最终，你应该能够将这些凭据存储在文件中。我将我的凭据存储在根目录下的一个名为 .caldav 的文件中：import os with open(os.path.expanduser("~/.caldav")) as fpin: username, password = fpin.read().split() 切勿将用户名和密码直接放在 Jupyter Notebook 的笔记本中！它们可能会很容易因 git push 的错误而导致泄漏。下一步是使用方便的 PyPI caldav 库。我找到了我的电子邮件服务的 CalDAV 服务器（你可能有所不同）：import caldav client = caldav.DAVClient(url="https://caldav.fastmail.com/dav/", username=username, password=password) CalDAV 有一个称为 principal（主键）的概念。它是什么并不重要，只要知道它是你用来访问日历的东西就行了：principal = client.principal() calendars = principal.calendars() 从字面上讲，日历就是关于时间的。访问事件之前，你需要确定一个时间范围。默认一星期就好：from dateutil import tz import datetime now = datetime.datetime.now(tz.tzutc()) since = now - datetime.timedelta(days=7) 大多数人使用的日历不止一个，并且希望所有事件都在一起出现。itertools.chain.from_iterable 方法使这一过程变得简单：import itertools raw_events = list( itertools.chain.from_iterable( calendar.date_search(start=since, end=now, expand=True) for calendar in calendars ) ) 将所有事件读入内存很重要，以 API 原始的本地格式进行操作是重要的实践。这意味着在调整解析、分析和显示代码时，无需返回到 API 服务刷新数据。但 “原始” 真的是原始，事件是以特定格式的字符串出现的：print(raw_events[12].data) BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CyrusIMAP.org/Cyrus 3.3.0-232-g4bdb081-fm-20200825.002-g4bdb081a//EN BEGIN:VEVENT DTEND:20200825T230000Z DTSTAMP:20200825T181915Z DTSTART:20200825T220000Z SUMMARY:Busy UID: 1302728i-040000008200E00074C5B7101A82E00800000000D939773EA578D601000000000 000000010000000CD71CC3393651B419E9458134FE840F5 END:VEVENT END:VCALENDAR 幸运的是，PyPI 可以再次使用另一个辅助库 vobject 解围：import io import vobject def parse_event(raw_event): data = raw_event.data parsed = vobject.readOne(io.StringIO(data)) contents = parsed.vevent.contents return contents parse_event(raw_events[12]) {'dtend': [<DTEND{}2020-08-25 23:00:00+00:00>], 'dtstamp': [<DTSTAMP{}2020-08-25 18:19:15+00:00>], 'dtstart': [<DTSTART{}2020-08-25 22:00:00+00:00>], 'summary': [<SUMMARY{}Busy>], 'uid': [<UID{}1302728i-040000008200E00074C5B7101A82E00800000000D939773EA578D601000000000000000010000000CD71CC3393651B419E9458134FE840F5>]} 好吧，至少好一点了。仍有一些工作要做，将其转换为合理的 Python 对象。第一步是 拥有 一个合理的 Python 对象。attrs 库提供了一个不错的开始：import attr from __future__ import annotations @attr.s(auto_attribs=True, frozen=True) class Event: start: datetime.datetime end: datetime.datetime timezone: Any summary: str 是时候编写转换代码了！第一个抽象从解析后的字典中获取值，不需要所有的装饰：def get_piece(contents, name): return contents[name][0].value get_piece(_, "dtstart") datetime.datetime(2020, 8, 25, 22, 0, tzinfo=tzutc()) 日历事件总有一个“开始”、有一个“结束”、有一个 “持续时间”。一些谨慎的解析逻辑可以将两者协调为同一个 Python 对象：def from_calendar_event_and_timezone(event, timezone): contents = parse_event(event) start = get_piece(contents, "dtstart") summary = get_piece(contents, "summary") try: end = get_piece(contents, "dtend") except KeyError: end = start + get_piece(contents, "duration") return Event(start=start, end=end, summary=summary, timezone=timezone) 将事件放在 本地 时区而不是 UTC 中很有用，因此使用本地时区：my_timezone = tz.gettz() from_calendar_event_and_timezone(raw_events[12], my_timezone) Event(start=datetime.datetime(2020, 8, 25, 22, 0, tzinfo=tzutc()), end=datetime.datetime(2020, 8, 25, 23, 0, tzinfo=tzutc()), timezone=tzfile('/etc/localtime'), summary='Busy') 既然事件是真实的 Python 对象，那么它们实际上应该具有附加信息。幸运的是，可以将方法添加到类中。但是要弄清楚哪个事件发生在哪一天不是很直接。你需要在 本地 时区中选择一天：def day(self): offset = self.timezone.utcoffset(self.start) fixed = self.start + offset return fixed.date() Event.day = property(day) print(_.day) 2020-08-25 事件在内部始终是以“开始”/“结束”的方式表示的，但是持续时间是有用的属性。持续时间也可以添加到现有类中：def duration(self): return self.end - self.start Event.duration = property(duration) print(_.duration) 1:00:00 现在到了将所有事件转换为有用的 Python 对象了：all_events = [from_calendar_event_and_timezone(raw_event, my_timezone) for raw_event in raw_events] 全天事件是一种特例，可能对分析生活没有多大用处。现在，你可以忽略它们：# ignore all-day events all_events = [event for event in all_events if not type(event.start) == datetime.date] 事件具有自然顺序 —— 知道哪个事件最先发生可能有助于分析：all_events.sort(key=lambda ev: ev.start) 现在，事件已排序，可以将它们加载到每天：import collections events_by_day = collections.defaultdict(list) for event in all_events: events_by_day[event.day].append(event) 有了这些，你就有了作为 Python 对象的带有日期、持续时间和序列的日历事件。用 Python 报到你的生活现在是时候编写报告代码了！带有适当的标题、列表、重要内容以粗体显示等等，有醒目的格式是很意义。这就是一些 HTML 和 HTML 模板。我喜欢使用 Chameleon：template_content = """ Day Thing """ Chameleon 的一个很酷的功能是使用它的 html 方法渲染对象。我将以两种方式使用它：摘要将以粗体显示对于大多数活动，我都会删除摘要（因为这是我的个人信息）def __html__(self): offset = my_timezone.utcoffset(self.start) fixed = self.start + offset start_str = str(fixed).split("+")[0] summary = self.summary if summary != "Busy": summary = "<REDACTED>" return f"{summary[:30]} -- {start_str} ({self.duration})" Event.__html__ = __html__ 为了简洁起见，将该报告切成每天的：import chameleon from IPython.display import HTML template = chameleon.PageTemplate(template_content) html = template(items=itertools.islice(events_by_day.items(), 3, 4)) HTML(html) 渲染后，它将看起来像这样：2020-08-25 -- 2020-08-25 08:30:00 (0:45:00) -- 2020-08-25 10:00:00 (1:00:00) -- 2020-08-25 11:30:00 (0:30:00) -- 2020-08-25 13:00:00 (0:25:00)Busy -- 2020-08-25 15:00:00 (1:00:00) -- 2020-08-25 15:00:00 (1:00:00) -- 2020-08-25 19:00:00 (1:00:00) -- 2020-08-25 19:00:12 (1:00:00)Python 和 Jupyter 的无穷选择通过解析、分析和报告各种 Web 服务所拥有的数据，这只是你可以做的事情的表面。为什么不对你最喜欢的服务试试呢？via: https://opensource.com/article/20/9/calendar-jupyter作者：Moshe Zadka 选题：lujun9972 译者：stevenzdg988 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
用 Jupyter 和 Python 在你的日常写作背后实现一些自动化。有些人会遵循传统，制定一年的计划。不过，一年的时间很长，所以我以季节性的主题或轨迹来规划。每个季度，我都会坐下来，看看即将到来的三个月的季节，并决定在这段时间里我将努力做什么。对于我最新的主题，我决定要每天写一篇日记。我喜欢有明确的承诺，所以我承诺每天写 5 分钟。我也喜欢有可观察的承诺，哪怕只是对我而言，所以我把我的记录放在 Git 里。我决定在写日记的过程中实现一些自动化，于是我使用了我最喜欢的自动化工具：Jupyter。Jupyter 有一个有趣的功能 ipywidgets，这是一套用于 Jupyter Notebooks、JupyterLab 和 IPython 内核的交互式 HTML 组件。如果你想跟着本文的代码走，请注意，让你的 JupyterLab 实例支持组件可能有点复杂，请按照这些说明来进行设置。导入 ipywidgets 模块首先，你需要导入一堆东西，比如 ipywidgets 和 Twisted。Twisted 模块可以用来创建一个异步时间计数器：import twisted.internet.asyncioreactor twisted.internet.asyncioreactor.install() from twisted.internet import reactor, task import ipywidgets, datetime, subprocess, functools, os 设置定时条目用 Twisted 实现时间计数器是利用了 task.LoopingCall。然而，结束循环调用的唯一方法是用一个异常。倒计时时钟总会停止，所以你需要一个自定义的异常来指示“一切正常；计数器结束”：class DoneError(Exception): pass 现在你已经写好了异常，你可以写定时器了。第一步是创建一个 ipywidgets.Label 的文本标签组件。循环使用 divmod 计算出分和秒，然后设置标签的文本值：def time_out_counter(reactor): label = ipywidgets.Label("Time left: 5:00") current_seconds = datetime.timedelta(minutes=5).total_seconds() def decrement(count): nonlocal current_seconds current_seconds -= count time_left = datetime.timedelta(seconds=max(current_seconds, 0)) minutes, left = divmod(time_left, minute) seconds = int(left.total_seconds()) label.value = f"Time left: {minutes}:{seconds:02}" if current_seconds < 0: raise DoneError("finished") minute = datetime.timedelta(minutes=1) call = task.LoopingCall.withCount(decrement) call.reactor = reactor d = call.start(1) d.addErrback(lambda f: f.trap(DoneError)) return d, label 从 Jupyter 组件中保存文本下一步是写一些东西，将你输入的文字保存到一个文件中，并提交到 Git。另外，由于你要写 5 分钟的日记，你需要一个能给你提供写字区域的组件（滚动肯定是可以的，但一次能看到更多的文字就更好了）。这就用到了组件 Textarea，这是一个你可以书写的文本字段，而 Output 则是用来给出反馈的。这一点很重要，因为 git push 可能会花点时间或失败，这取决于网络。如果备份失败，用反馈提醒用户很重要：def editor(fname): textarea = ipywidgets.Textarea(continuous_update=False) textarea.rows = 20 output = ipywidgets.Output() runner = functools.partial(subprocess.run, capture_output=True, text=True, check=True) def save(_ignored): with output: with open(fname, "w") as fpout: fpout.write(textarea.value) print("Sending...", end='') try: runner(["git", "add", fname]) runner(["git", "commit", "-m", f"updated {fname}"]) runner(["git", "push"]) except subprocess.CalledProcessError as exc: print("Could not send") print(exc.stdout) print(exc.stderr) else: print("Done") textarea.observe(save, names="value") return textarea, output, save continuous_update=False 是为了避免每个字符都保存一遍并发送至 Git。相反，只要脱离输入焦点，它就会保存。这个函数也返回 save 函数，所以可以明确地调用它。创建一个布局最后，你可以使用 ipywidgets.VBox 把这些东西放在一起。这是一个包含一些组件并垂直显示的东西。还有一些其他的方法来排列组件，但这足够简单：def journal(): date = str(datetime.date.today()) title = f"Log: Startdate {date}" filename = os.path.join(f"{date}.txt") d, clock = time_out_counter(reactor) textarea, output, save = editor(filename) box = ipywidgets.VBox([ ipywidgets.Label(title), textarea, clock, output ]) d.addCallback(save) return box biu！你已经定义了一个写日记的函数了，所以是时候试试了。journal() 你现在可以写 5 分钟了！via: https://opensource.com/article/20/11/daily-journal-jupyter作者：Moshe Zadka 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
Jupyter 不仅仅是一个数据分析工具，让我们看看如何以最有创意的方式使用这个基于 Python 的软件。Jupyter 项目提供了用 JupyterLab 和 Jupyter Notebook 等交互式编写软件的技术方式。这个软件通常用于数据分析，但你可能不知道（Jupyter 社区也没有想到），你可以用它做多少事情。以下是我使用 Jupyter 的五大意想不到的创造性方法。1、处理图像在图像编辑和处理方面，有很多很好的开源工具 —— 从那些可以与 Photoshop 媲美的工具到实验性的 Glimpse。但即使有这么多选择，有时我还是不想离开 Python 的世界。幸运的是，Jupyter 是一个做轻量级图像处理的好选择。利用 Jupyter 直接将 Pillow 对象显示为图像的优势，让你可以尽情地对图片进行实验。我甚至还用它给孩子做了一个涂色画。2、做一个 SSH 跳板遥控器由于 JupyterLab 可以让你上传和下载文件、编辑文件，甚至运行终端，所以它拥有制作 SSH 跳板环境所需的所有部件。通过一些 SSH 转发魔法，你可以让 Jupyter 成为防火墙另一边的远程控制台。3、开发 Web 应用程序我最喜欢的使用 Jupyter 的方式之一是用于一种意想不到的软件开发。我做了一次演讲，在演讲中，我使用 Jupyter Notebook 实时开发了一个 Web 应用。讲演的最后是一个简单的表单，它是 XSS 和 CSS 安全的，并包括一些轻量级的服务器端计算。一个日常的 Jupyter 用户可能不会期望它是一个最棒的 Web 开发环境，但它是一个非常强大的环境。4、从你喜欢的服务中提取报告JupyterLab 中的数据分析是一种常见的用法，但 自我提升分析 self-improvement analysis 呢？你可以使用 Jupyter 来分析你的日历。如果你最喜欢的服务允许 API 导出，甚至可以让你导出一个 CSV，你可以将这些与你的日历进行关联。如果你发现你在社交媒体上发帖的时候，你的日历上写着你应该和你的经理开会，那 Jupyter 也救不了你！5、开发游戏对于扩大对 Jupyter Notebook 的期望值，我最喜欢的方式是和孩子一起建立一个游戏。我之前写过这方面的文章，有一个使用 PursuedPyBear 和 Jupyter 编写游戏的分步教程。在试图弄清游戏机制时，这种迭代式的游戏开发方法特别有用。能够在游戏中途改变规则（对不起，我必须得这样做）是一个改变游戏规则的方法。你甚至可以使用 IPywidgets 来修改数字参数，就像这个视频所示。下载电子书JupyterLab 和 Jupyter Notebooks 提供了一个不可思议的实验环境。下载这本指南，其中包含了以令人吃惊的方式使用 Jupyter 的教程。你是如何以创造性的方式使用它的？在下面的评论中分享你的最爱。via: https://opensource.com/article/20/11/surprising-jupyter作者：Moshe Zadka 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
有了 Jupyter、PyHamcrest，用一点测试的代码把它们连在一起，你就可以教任何适用于单元测试的 Python 内容。关于 Ruby 社区的一些事情一直让我印象深刻，其中两个例子是对测试的承诺和对易于上手的强调。这两方面最好的例子是 Ruby Koans，在这里你可以通过修复测试来学习 Ruby。要是我们能把这些神奇的工具也用于 Python，我们应该可以做得更好。是的，使用 Jupyter Notebook、PyHamcrest，再加上一点类似于胶带的粘合代码，我们可以做出一个包括教学、可工作的代码和需要修复的代码的教程。首先，需要一些“胶布”。通常，你会使用一些漂亮的命令行测试器来做测试，比如 pytest 或 virtue。通常，你甚至不会直接运行它。你使用像 tox 或 nox 这样的工具来运行它。然而，对于 Jupyter 来说，你需要写一小段粘合代码，可以直接在其中运行测试。幸运的是，这个代码又短又简单：import unittest def run_test(klass): suite = unittest.TestLoader().loadTestsFromTestCase(klass) unittest.TextTestRunner(verbosity=2).run(suite) return klass 现在，装备已经就绪，可以进行第一次练习了。在教学中，从一个简单的练习开始，建立信心总是一个好主意。那么，让我们来修复一个非常简单的测试：@run_test class TestNumbers(unittest.TestCase): def test_equality(self): expected_value = 3 # 只改这一行 self.assertEqual(1+1, expected_value) test_equality (__main__.TestNumbers) ... FAIL ====================================================================== FAIL: test_equality (__main__.TestNumbers) ---------------------------------------------------------------------- Traceback (most recent call last): File "<ipython-input-7-5ebe25bc00f3>", line 6, in test_equality self.assertEqual(1+1, expected_value) AssertionError: 2 != 3 ---------------------------------------------------------------------- Ran 1 test in 0.002s FAILED (failures=1) “只改这一行” 对学生来说是一个有用的标记。它准确地表明了需要修改的内容。否则，学生可以通过将第一行改为 return 来修复测试。在这种情况下，修复很容易：@run_test class TestNumbers(unittest.TestCase): def test_equality(self): expected_value = 2 # 修复后的代码行 self.assertEqual(1+1, expected_value) test_equality (__main__.TestNumbers) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.002s OK 然而，很快，unittest 库的原生断言将被证明是不够的。在 pytest 中，通过重写 assert 中的字节码来解决这个问题，使其具有神奇的属性和各种启发式方法。但这在 Jupyter notebook 中就不容易实现了。是时候挖出一个好的断言库了：PyHamcrest。from hamcrest import * @run_test class TestList(unittest.TestCase): def test_equality(self): things = [1, 5, # 只改这一行 3] assert_that(things, has_items(1, 2, 3)) test_equality (__main__.TestList) ... FAIL ====================================================================== FAIL: test_equality (__main__.TestList) ---------------------------------------------------------------------- Traceback (most recent call last): File "<ipython-input-11-96c91225ee7d>", line 8, in test_equality assert_that(things, has_items(1, 2, 3)) AssertionError: Expected: (a sequence containing <1> and a sequence containing <2> and a sequence containing <3>) but: a sequence containing <2> was <[1, 5, 3]> ---------------------------------------------------------------------- Ran 1 test in 0.004s FAILED (failures=1) PyHamcrest 不仅擅长灵活的断言，它还擅长清晰的错误信息。正因为如此，问题就显而易见了。[1, 5, 3] 不包含 2，而且看起来很丑：@run_test class TestList(unittest.TestCase): def test_equality(self): things = [1, 2, # 改完的行 3] assert_that(things, has_items(1, 2, 3)) test_equality (__main__.TestList) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK 使用 Jupyter、PyHamcrest 和一点测试的粘合代码，你可以教授任何适用于单元测试的 Python 主题。例如，下面可以帮助展示 Python 从字符串中去掉空白的不同方法之间的差异。source_string = " hello world " @run_test class TestList(unittest.TestCase): # 这是个赠品：它可以工作！ def test_complete_strip(self): result = source_string.strip() assert_that(result, all_of(starts_with("hello"), ends_with("world"))) def test_start_strip(self): result = source_string # 只改这一行 assert_that(result, all_of(starts_with("hello"), ends_with("world "))) def test_end_strip(self): result = source_string # 只改这一行 assert_that(result, all_of(starts_with(" hello"), ends_with("world"))) test_complete_strip (__main__.TestList) ... ok test_end_strip (__main__.TestList) ... FAIL test_start_strip (__main__.TestList) ... FAIL ====================================================================== FAIL: test_end_strip (__main__.TestList) ---------------------------------------------------------------------- Traceback (most recent call last): File "<ipython-input-16-3db7465bd5bf>", line 19, in test_end_strip assert_that(result, AssertionError: Expected: (a string starting with ' hello' and a string ending with 'world') but: a string ending with 'world' was ' hello world ' ====================================================================== FAIL: test_start_strip (__main__.TestList) ---------------------------------------------------------------------- Traceback (most recent call last): File "<ipython-input-16-3db7465bd5bf>", line 14, in test_start_strip assert_that(result, AssertionError: Expected: (a string starting with 'hello' and a string ending with 'world ') but: a string starting with 'hello' was ' hello world ' ---------------------------------------------------------------------- Ran 3 tests in 0.006s FAILED (failures=2) 理想情况下，学生们会意识到 .lstrip() 和 .rstrip() 这两个方法可以满足他们的需要。但如果他们不这样做，而是试图到处使用 .strip() 的话：source_string = " hello world " @run_test class TestList(unittest.TestCase): # 这是个赠品：它可以工作！ def test_complete_strip(self): result = source_string.strip() assert_that(result, all_of(starts_with("hello"), ends_with("world"))) def test_start_strip(self): result = source_string.strip() # 改完的行 assert_that(result, all_of(starts_with("hello"), ends_with("world "))) def test_end_strip(self): result = source_string.strip() # 改完的行 assert_that(result, all_of(starts_with(" hello"), ends_with("world"))) test_complete_strip (__main__.TestList) ... ok test_end_strip (__main__.TestList) ... FAIL test_start_strip (__main__.TestList) ... FAIL ====================================================================== FAIL: test_end_strip (__main__.TestList) ---------------------------------------------------------------------- Traceback (most recent call last): File "<ipython-input-17-6f9cfa1a997f>", line 19, in test_end_strip assert_that(result, AssertionError: Expected: (a string starting with ' hello' and a string ending with 'world') but: a string starting with ' hello' was 'hello world' ====================================================================== FAIL: test_start_strip (__main__.TestList) ---------------------------------------------------------------------- Traceback (most recent call last): File "<ipython-input-17-6f9cfa1a997f>", line 14, in test_start_strip assert_that(result, AssertionError: Expected: (a string starting with 'hello' and a string ending with 'world ') but: a string ending with 'world ' was 'hello world' ---------------------------------------------------------------------- Ran 3 tests in 0.007s FAILED (failures=2) 他们会得到一个不同的错误信息，显示去除了过多的空白：source_string = " hello world " @run_test class TestList(unittest.TestCase): # 这是个赠品：它可以工作！ def test_complete_strip(self): result = source_string.strip() assert_that(result, all_of(starts_with("hello"), ends_with("world"))) def test_start_strip(self): result = source_string.lstrip() # Fixed this line assert_that(result, all_of(starts_with("hello"), ends_with("world "))) def test_end_strip(self): result = source_string.rstrip() # Fixed this line assert_that(result, all_of(starts_with(" hello"), ends_with("world"))) test_complete_strip (__main__.TestList) ... ok test_end_strip (__main__.TestList) ... ok test_start_strip (__main__.TestList) ... ok ---------------------------------------------------------------------- Ran 3 tests in 0.005s OK 在一个比较真实的教程中，会有更多的例子和更多的解释。这种使用 Jupyter Notebook 的技巧，有的例子可以用，有的例子需要修正，可以用于实时教学，可以用于视频课，甚至，可以用更多的其它零散用途，让学生自己完成一个教程。现在就去分享你的知识吧!via: https://opensource.com/article/20/9/teach-python-jupyter作者：Moshe Zadka 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
把 Jupyter 变成一个远程管理控制台。SSH 是一个强大的远程管理工具，但有些细节还不够好。编写一个成熟的远程管理控制台听起来好像是一件很费劲的事情。当然，开源社区中肯定有人已经写了一些东西吧？是的，他们已经写出来了，它的名字是 Jupyter。你可能会认为 Jupyter 是那些数据科学家用来分析一周内的广告点击趋势之类的工具。这并没有错，它确实是的，而且它是一个很好的工具。但这仅仅刻画是它的表面。关于 SSH 端口转发有时，你可以通过 22 端口进入一台服务器。一般你也连接不到其他端口。也许你是通过另一个有更多访问权限的“堡垒机”，或者限制主机或端口的网络防火墙访问 SSH。当然，限制访问的 IP 范围是有充分理由的。SSH 是远程管理的安全协议，但允许任何人连接到任何端口是相当不必要的。这里有一个替代方案：运行一个简单的 SSH 端口转发命令，将本地端口转发到一个“远程”本地连接上。当你运行像 -L 8111:127.0.0.1:8888 这样的 SSH 端口转发命令时，你是在告诉 SSH 将你的本地端口 8111 转发到它认为的“远程”主机 127.0.0.1:8888。远程主机认为 127.0.0.1 就是它本身。就像在《芝麻街》节目一样，“这里”是一个微妙的词。地址 127.0.0.1 就是你告诉网络的“这里”。实际动手学习这可能听起来很混乱，但运行比解释它更简单。$ ssh -L 8111:127.0.0.1:8888 moshez@172.17.0.3 Linux 6ad096502e48 5.4.0-40-generic #44-Ubuntu SMP Tue Jun 23 00:01:04 UTC 2020 x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Wed Aug 5 22:03:25 2020 from 172.17.0.1 $ jupyter/bin/jupyter lab --ip=127.0.0.1 [I 22:04:29.771 LabApp] JupyterLab application directory is /home/moshez/jupyter/share/jupyter/lab [I 22:04:29.773 LabApp] Serving notebooks from local directory: /home/moshez [I 22:04:29.773 LabApp] Jupyter Notebook 6.1.1 is running at: [I 22:04:29.773 LabApp] http://127.0.0.1:8888/?token=df91012a36dd26a10b4724d618b2e78cb99013b36bb6a0d1 <删节> 端口转发 8111 到 127.0.0.1，并在远程主机上启动 Jupyter，它在 127.0.0.1:8888 上监听。现在你要明白，Jupyter 在撒谎。它认为你需要连接到 8888 端口，但你把它转发到 8111 端口。所以，当你把 URL 复制到浏览器后，但在点击回车之前，把端口从 8888 修改为 8111。这就是你的远程管理控制台。如你所见，底部有一个“终端”图标。点击它可以启动一个终端。你可以运行一条命令。创建一个文件会在旁边的文件浏览器中显示出来。你可以点击该文件，在本地的编辑器中打开它。你还可以下载、重命名或删除文件：点击上箭头就可以上传文件了。那就上传上面的截图吧。最后说个小功能，Jupyter 可以让你直接通过双击远程图像查看。哦，对了，如果你想用 Python 做系统自动化，还可以用 Jupyter 打开笔记本。所以，下次你需要远程管理防火墙环境的时候，为什么不使用 Jupyter 呢？via: https://opensource.com/article/20/9/remote-management-jupyter作者：Moshe Zadka 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在过去，神谕和魔法师被认为拥有发现奥秘的力量，国王和统治者们会借助他们预测未来，或者至少是听取一些建议。如今我们生活在一个痴迷于将一切事情量化的社会里，这份工作就交给数据科学家了。数据科学家通过使用统计模型、数值分析，以及统计学之外的高级算法，结合数据库里已经存在的数据，去发掘、推断和预测尚不存在的数据（有时是关于未来的数据）。这就是为什么我们要做这么多的预测分析和规划分析。下面是一些可以借助数据科学家回答的问题：哪些学生有旷课倾向？每个人旷课的原因分别是什么？哪栋房子的售价比合理价格要高或者低？一栋房子的合理价格是多少？如何将我们的客户按照潜在的特质进行分组？这个孩子的早熟可能会在未来引发什么问题？我们的呼叫中心在明天早上 11 点 43 分会接收到多少次呼叫？我们的银行是否应该向这位客户发放贷款？请注意，这些问题的答案是在任何数据库里都查询不到的，因为它们尚不存在，需要被计算出来才行。这就是我们数据科学家从事的工作。在这篇文章中你会学习如何将 Fedora 系统打造成数据科学家的开发环境和生产系统。其中大多数基本软件都有 RPM 软件包，但是最先进的组件目前只能通过 Python 的 pip 工具安装。Jupyter IDE大多数现代数据科学家使用 Python 工作。他们工作中很重要的一部分是 探索性数据分析 Exploratory Data Analysis （EDA）。EDA 是一种手动进行的、交互性的过程，包括提取数据、探索数据特征、寻找相关性、通过绘制图形进行数据可视化并理解数据的分布特征，以及实现原型预测模型。Jupyter 是能够完美胜任该工作的一个 web 应用。Jupyter 使用的 Notebook 文件支持富文本，包括渲染精美的数学公式（得益于 mathjax）、代码块和代码输出（包括图形输出）。Notebook 文件的后缀是 .ipynb，意思是“交互式 Python Notebook”。搭建并运行 Jupyter首先，使用 sudo 安装 Jupyter 核心软件包：$ sudo dnf install python3-notebook mathjax sscg你或许需要安装数据科学家常用的一些附加可选模块：$ sudo dnf install python3-seaborn python3-lxml python3-basemap python3-scikit-image python3-scikit-learn python3-sympy python3-dask+dataframe python3-nltk设置一个用来登录 Notebook 的 web 界面的密码，从而避免使用冗长的令牌。你可以在终端里任何一个位置运行下面的命令：$ mkdir -p $HOME/.jupyter $ jupyter notebook password然后输入你的密码，这时会自动创建 $HOME/.jupyter/jupyter_notebook_config.json 这个文件，包含了你的密码的加密后版本。接下来，通过使用 SSLby 为 Jupyter 的 web 服务器生成一个自签名的 HTTPS 证书：$ cd $HOME/.jupyter; sscg配置 Jupyter 的最后一步是编辑 $HOME/.jupyter/jupyter_notebook_config.json 这个文件。按照下面的模版编辑该文件：{ "NotebookApp": { "password": "sha1:abf58...87b", "ip": "*", "allow_origin": "*", "allow_remote_access": true, "open_browser": false, "websocket_compression_options": {}, "certfile": "/home/aviram/.jupyter/service.pem", "keyfile": "/home/aviram/.jupyter/service-key.pem", "notebook_dir": "/home/aviram/Notebooks" } }/home/aviram/ 应该替换为你的文件夹。sha1:abf58...87b 这个部分在你创建完密码之后就已经自动生成了。service.pem 和 service-key.pem 是 sscg 生成的和加密相关的文件。接下来创建一个用来存放 Notebook 文件的文件夹，应该和上面配置里 notebook_dir 一致：$ mkdir $HOME/Notebooks你已经完成了配置。现在可以在系统里的任何一个地方通过以下命令启动 Jupyter Notebook：$ jupyter notebook或者是将下面这行代码添加到 $HOME/.bashrc 文件，创建一个叫做 jn 的快捷命令：alias jn='jupyter notebook'运行 jn 命令之后，你可以通过网络内部的任何一个浏览器访问 <https://your-fedora-host.com:8888> （LCTT 译注：请将域名替换为服务器的域名），就可以看到 Jupyter 的用户界面了，需要使用前面设置的密码登录。你可以尝试键入一些 Python 代码和标记文本，看起来会像下面这样：除了 IPython 环境，安装过程还会生成一个由 terminado 提供的基于 web 的 Unix 终端。有人觉得这很实用，也有人觉得这样不是很安全。你可以在配置文件里禁用这个功能。JupyterLab：下一代 JupyterJupyterLab 是下一代的 Jupyter，拥有更好的用户界面和对工作空间更强的操控性。在写这篇文章的时候 JupyterLab 还没有可用的 RPM 软件包，但是你可以使用 pip 轻松完成安装：$ pip3 install jupyterlab --user $ jupyter serverextension enable --py jupyterlab然后运行 jupiter notebook 命令或者 jn 快捷命令。访问 <http://your-linux-host.com:8888/lab> （LCTT 译注：将域名替换为服务器的域名）就可以使用 JupyterLab 了。数据科学家使用的工具在下面这一节里，你将会了解到数据科学家使用的一些工具及其安装方法。除非另作说明，这些工具应该已经有 Fedora 软件包版本，并且已经作为前面组件所需要的软件包而被安装了。NumpyNumpy 是一个针对 C 语言优化过的高级库，用来处理大型的内存数据集。它支持高级多维矩阵及其运算，并且包含了 log()、exp()、三角函数等数学函数。Pandas在我看来，正是 Pandas 成就了 Python 作为数据科学首选平台的地位。Pandas 构建在 Numpy 之上，可以让数据准备和数据呈现工作变得简单很多。你可以把它想象成一个没有用户界面的电子表格程序，但是能够处理的数据集要大得多。Pandas 支持从 SQL 数据库或者 CSV 等格式的文件中提取数据、按列或者按行进行操作、数据筛选，以及通过 Matplotlib 实现数据可视化的一部分功能。MatplotlibMatplotlib 是一个用来绘制 2D 和 3D 数据图像的库，在图象注解、标签和叠加层方面都提供了相当不错的支持。SeabornSeaborn 构建在 Matplotlib 之上，它的绘图功能经过了优化，更加适合数据的统计学研究，比如说可以自动显示所绘制数据的近似回归线或者正态分布曲线。StatsModelsStatsModels 为统计学和经济计量学的数据分析问题（例如线形回归和逻辑回归）提供算法支持，同时提供经典的 时间序列算法 家族 ARIMA。Scikit-learn作为机器学习生态系统的核心部件，Scikit 为不同类型的问题提供预测算法，包括 回归问题（算法包括 Elasticnet、Gradient Boosting、随机森林等等）、分类问题 和聚类问题（算法包括 K-means 和 DBSCAN 等等），并且拥有设计精良的 API。Scikit 还定义了一些专门的 Python 类，用来支持数据操作的高级技巧，比如将数据集拆分为训练集和测试集、降维算法、数据准备管道流程等等。XGBoostXGBoost 是目前可以使用的最先进的回归器和分类器。它并不是 Scikit-learn 的一部分，但是却遵循了 Scikit 的 API。XGBoost 并没有针对 Fedora 的软件包，但可以使用 pip 安装。使用英伟达显卡可以提升 XGBoost 算法的性能，但是这并不能通过 pip 软件包来实现。如果你希望使用这个功能，可以针对 CUDA （LCTT 译注：英伟达开发的并行计算平台）自己进行编译。使用下面这个命令安装 XGBoost：$ pip3 install xgboost --userImbalanced LearnImbalanced-learn 是一个解决数据欠采样和过采样问题的工具。比如在反欺诈问题中，欺诈数据相对于正常数据来说数量非常小，这个时候就需要对欺诈数据进行数据增强，从而让预测器能够更好地适应数据集。使用 pip 安装：$ pip3 install imblearn --userNLTKNatural Language toolkit（简称 NLTK）是一个处理人类语言数据的工具，举例来说，它可以被用来开发一个聊天机器人。SHAP机器学习算法拥有强大的预测能力，但并不能够很好地解释为什么做出这样或那样的预测。SHAP 可以通过分析训练后的模型来解决这个问题。使用 pip 安装：$ pip3 install shap --userKerasKeras 是一个深度学习和神经网络模型的库，使用 pip 安装：$ sudo dnf install python3-h5py $ pip3 install keras --userTensorFlowTensorFlow 是一个非常流行的神经网络模型搭建工具，使用 pip 安装：$ pip3 install tensorflow --userPhoto courtesy of FolsomNatural on Flickr (CC BY-SA 2.0).via: https://fedoramagazine.org/jupyter-and-data-science-in-fedora/作者：Avi Alkalay 选题：lujun9972 译者：chen-ni 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
对 Python 开发者而言，IPython 仍然是 Jupyter Notebook 的核心
Jupyter 项目提供的魔法般的开发体验很大程度上得益于它的 IPython 基因。最近刚刚写过我为什么觉得觉得 Jupyter 项目（特别是 JupyterLab）提供了一种 魔法般的 Python 开发体验。在研究这些不同项目之间的关联的时候，我回顾了一下 Jupyter 最初从 IPython 分支出来的这段历史。正如 Jupyter 项目的 大拆分™ 声明 所说:“如果你不明白 Jupyter 是什么，这么说吧，它拥有和 IPython 同样的代码，并且是由同一批人开发的，只不过取了一个新名字、安了一个新家。”下面这个注脚进一步说明了这一点：“我从声明中解读出来的信息是，‘Jupyter 和 IPython 非常相似，但是拥有多种语言’，这也可以很好地解释为什么这个项目的名字已经不再需要包含 Python，因为当时它已经支持多种语言了。”我明白 Jupyter Notebook 和 IPython 都是从同样的源代码里分支出来的，但是不太清楚 IPython 项目的现状。在大拆分™ 之后它是已经不再被需要了，还是在以另一种方式延续着？后来我惊讶地发现，IPython 仍然不断在为 Python 使用者提供价值，它正是 Jupyter 体验的核心部分。下面是 Jupyter 常见问题页面的一段截取：有什么语言是需要预装的吗？是的，安装 Jupyter Notebook 会首先安装 IPython 内核。这样我们就可以在 notebook 上运行 Python 语言了。现在我明白了，在 JupyterLab（以及 Jupyter Notebook）上编写 Python 程序仍然需要依赖 IPython 内核的持续开发。不仅如此，IPython 还充当了最为强大的默认内核的角色，根据 这份文档，它是其它语言内核之间的枢纽，节省了很多开发时间和精力。现在唯一的问题是，IPython 本身可以做什么呢？IPython 如今的作用IPython 提供了一个强大的、交互性的 Python shell，以及 Jupyter 的内核。安装完成之后，我可以在任何命令行运行 ipython 本身，将它当作一个（比默认 Python shell 好太多的）Python shell 来使用：$ ipython Python 3.7.3 (default, Mar 27 2019, 09:23:15) Type 'copyright', 'credits' or 'license' for more information IPython 7.4.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: import numpy as np In [2]: example = np.array([5, 20, 3, 4, 0, 2, 12]) In [3]: average = np.average(example) In [4]: print(average) 6.571428571428571这就让我们发现了一个更为重要的问题：是 IPython 让 JupyterLab 可以在项目中执行代码，并且支持了一系列被称为 Magic 的功能（感谢 Nicholas Reith 在我上一篇文章的评论里提到这点）。IPython 让魔法成为现实JupyterLab 和其它使用 IPython 的前端工具可以让你感觉像是在最喜欢的 IDE 或者是终端模拟器的环境下工作。我非常喜欢 点文件 快捷键功能，Magic 也有类似点文件的特征。比如说，可以试一下 %bookmark 这个命令。我把默认开发文件夹 ~/Develop 关联到了一个可以在任何时候直接跳转的快捷方式上。%bookmark、%cd，以及我在前一篇文章里介绍过的 ! 操作符，都是由 IPython 支持的。正如这篇 文档 所说：Jupyter 用户你们好：Magic 功能是 IPython 内核提供的专属功能。一个内核是否支持 Magic 功能是由该内核的开发者针对该内核所决定的。写在最后作为一个好奇的新手，我之前并不是特别确定 IPython 是否仍然和 Jupyter 生态还有任何联系。现在我对 IPython 的持续开发有了新的认识和，并且意识到它正是 JupyterLab 强大的用户体验的来源。这也是相当有才华的一批贡献者进行最前沿研究的成果，所以如果你在学术论文中使用到了 Jupyter 项目的话别忘了引用他们。为了方便引用，他们还提供了一个 现成的引文。如果你在考虑参与哪个开源项目的贡献的话，一定不要忘了 IPython 哦。记得看看 最新发布说明，在这里可以找到 Magic 功能的完整列表。via: https://opensource.com/article/19/6/ipython-still-heart-jupyterlab作者：Matthew Broberg 选题：lujun9972 译者：chen-ni 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
通过 Jupyter 使用实时代码、方程式和可视化及文本创建交互式的共享笔记本。自从有了纸莎草纸以来，出版人们一直在努力以吸引读者的方式来格式化数据。尤其是在数学、科学、和编程领域，设计良好的图表、插图和方程式可以成为帮助人们理解技术信息的关键。Jupyter Notebook 通过重新构想我们如何制作教学文本来解决这个问题。Jupyter （我在 2017 年 10 月在 All Things Open 上首次了解到）是一款开源应用程序，它使用户能够创建包含实时代码、方程式、可视化和文本的交互式共享笔记本。Jupyter 从 IPython 项目发展而来，它是个具有交互式 shell 和基于浏览器的笔记本，支持代码、文本和数学表达式。Jupyter 支持超过 40 种编程语言，包括 Python、R 和 Julia，其代码可以导出为 HTML、LaTeX、PDF、图像和视频，或者作为 IPyhton 笔记本与其他用户共享。一个有趣的事实是：“Jupyter” 是 “Julia、Python 和 R” 的缩写。根据 Jupyter 项目网站介绍，它的一些用途包括“数据清理和转换，数值模拟，统计建模，数据可视化，机器学习等等”。科学机构正在使用 Jupyter Notebooks 来解释研究结果。代码可以来自实际数据，可以调整和重新调整以可视化成不同的结果和情景。通过这种方式，Jupyter Notebooks 变成了生动的文本和报告。安装并开始 JupyterJupyter 软件是开源的，其授权于修改过的 BSD 许可证，它可以安装在 Linux、MacOS 或 Windows 上。有很多种方法可以安装 Jupyter；我在 Linux 和 MacOS 上试过 PIP 和 Anaconda 安装方式。PIP 安装要求你的计算机上已经安装了 Python；Jupyter 推荐 Python 3。由于 Python 3 已经安装在我的电脑上，我通过在终端（在 Linux 或 Mac 上）运行以下命令来安装 Jupyter：$ python3 -m pip install --upgrade pip $ python3 -m pip install jupyter 在终端提示符输入以下命令立即启动应用程序：$ jupyter notebook 很快，我的浏览器打开并显示了我在 http://localhost:8888 的 Jupyter Notebook 服务器。（支持的浏览器有 Google Chrome、Firefox 和 Safari）在右上角有一个标有 “New” 的下拉菜单，它使我能够根据自己的指示和代码快速创建新的笔记本。请注意，我的新笔记本默认为 Python 3，这是我目前的环境。一个带有一些默认值的新笔记本，它可以被改变（包括笔记本的名字），已打开。笔记本有两种不同的模式：“命令模式”和“编辑模式”。命令模式允许你添加或删除单元格。你可以通过按下 Escape 键进入命令模式，按 Enter 键或单击单元格进入编辑模式。单元格周围的绿色高亮显示你处于编辑模式，蓝色高亮显示你处于命令模式。以下笔记本处于命令模式并准备好执行单元中的 Python 代码。注意，我已将笔记本的名称更改为 “First Notebook”。使用 JupyterJupyter Notebooks 的强大之处在于除了能够输入代码之外，你还可以用 Markdown 添加叙述性和解释性文本。我想添加一个标题，所以我在代码上面添加了一个单元格，并以 Markdown 输入了一个标题。当我按下 Ctrl+Enter 时，我的标题转换为 HTML。（LCTT 译注：或者可以按下 Run 按钮。）我可以通过在命令前追加 ! 来添加 Bash 命令或脚本的输出。我也可以利用 IPython 的 line magic 和 cell magic 命令。你可以通过在代码单元内附加 % 或 %% 符号来列出魔术命令。例如，%lsmagic 将输出所有可用于 Jupyter notebooks 的魔法命令。这些魔术命令的例子包括 %pwd——它输出当前工作目录（例如 /Users/YourName）和 %ls——它列出当前工作目录中的所有文件和子目录。另一个神奇命令显示从笔记本中的 matplotlib 生成的图表。%%html 将该单元格中的任何内容呈现为 HTML，这对嵌入视频和链接很有用，还有 JavaScript 和 Bash 的单元魔术命令。如果你需要更多关于使用 Jupyter Notebooks 和它的特性的信息，它的帮助部分是非常完整的。人们用许多有趣的方式使用 Jupyter Notebooks；你可以在这个展示栏目里找到一些很好的例子。你如何使用 Jupyter 笔记本？请在下面的评论中分享你的想法。via: https://opensource.com/article/18/3/getting-started-jupyter-notebooks作者：Don Watkins 选题：lujun9972 译者：MjSeven 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出