比如执行这段代码失败:
#+begin_src python :session
if True:
1
2
#+end_src
*Python* Buffer 中的内容
if True:
Python 3.6.4 (default, Mar 9 2018, 23:15:03)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
1
>>> 2
...
... open('/var/folders/7f/s191h4q97p90374yw15ssrs00000gn/T/babel-YA00Ot/python-DOI8ZG', 'w').write(str(_))
File "<stdin>", line 3
2
^
SyntaxError: invalid syntax
>>>
>>> 'org_babel_python_eoe'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
>>> 'org_babel_python_eoe'
>>>
下面这段代码可以:
#+begin_src python :session
if True:
1
2
#+end_src
#+RESULTS:
: 2
但 Python 没有这个要求吧,因为第一段代码保存到 foo.py
,然后 python foo.py
没有报错。
xuchunyang:
if True:
1
2
首先这个是錯的。Python 用的是 if ...: elif ... else: ...
句式。
if True:
1
else:
2
xuchunyang:
下面这段代码可以:
因為
if True:
1
是一個合法语句,第二段代码结果的 2
实际是 2
的返回值。
Python 3.6.4 (default, Jan 13 2018, 17:39:32)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> if True:
... 1 # if statement ends here
...
1
>>> 2
2
>>> ^D
另外 interactive test 还是直接上 REPL 吧,Python 又不是 C 这種要编绎才能运行的。你看你这樣用就出了理解误差。
那是你的理解,1 跟 2 没有关系,我举的例子不好,用这个吧
if True:
print("True is found")
print("Program ends here")
if 语句没有错:
$ echo '
if True:
print(1)
print(2)' | python
1
2
应该是 orgmode 在处理空行的时候出了问题。没空行的时候,临时文件的内容是 org_babel_python_eoe
,正常应该是最后一个表达式的结果 2
。
1 个赞
@twlz0ne
这不算是是 org 的问題,因為 org 的 :session
执行 python 代碼块用的是 REPL,而 python 出于某種原因 做成了 REPL 中的 if 要換行,batch 不用。
我上面的 REPL 例子中就是要多一个空行來结束 if statement。
3 个赞
所以还是 org 的问题嘛。
@xuchunyang 我简单修复了一下:
(defun my/org-babel-python-evaluate-session
(session body &optional result-type result-params)
"Pass BODY to the Python process in SESSION.
If RESULT-TYPE equals `output' then return standard output as a
string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp."
(let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
(dump-last-value
(lambda
(tmp-file pp)
(mapc
(lambda (statement) (insert statement) (funcall send-wait))
(if pp
(list
"import pprint"
(format "open('%s', 'w').write(pprint.pformat(_))"
(org-babel-process-file-name tmp-file 'noquote)))
(list (format "open('%s', 'w').write(str(_))"
(org-babel-process-file-name tmp-file
'noquote)))))))
;; ----------- 8< -----------
(last-indent 0)
;; ----------- >8 -----------
(input-body (lambda (body)
(mapc (lambda (line)
;; ----------- 8< -----------
(let ((curr-indent (string-match "[^\s]" line)))
(if curr-indent
(progn
(when (< curr-indent last-indent)
(message "[ob-python] >>> <insert_blank>")
(insert "")
(funcall send-wait))
(setq last-indent curr-indent))
(setq last-indent 0)))
(message "[ob-python] >>> %S" line)
;; ----------- >8 -----------
(insert line)
(funcall send-wait))
(split-string body "[\r\n]"))
(funcall send-wait)))
(results
(pcase result-type
(`output
(let ((body (if (string-match-p ".\n+." body) ; Multiline
(let ((tmp-src-file (org-babel-temp-file
"python-")))
(with-temp-file tmp-src-file (insert body))
(format org-babel-python--exec-tmpfile
tmp-src-file))
body)))
(mapconcat
#'org-trim
(butlast
(org-babel-comint-with-output
(session org-babel-python-eoe-indicator t body)
(funcall input-body body)
(funcall send-wait) (funcall send-wait)
(insert org-babel-python-eoe-indicator)
(funcall send-wait))
2) "\n")))
(`value
(let ((tmp-file (org-babel-temp-file "python-")))
(org-babel-comint-with-output
(session org-babel-python-eoe-indicator nil body)
(let ((comint-process-echoes nil))
(funcall input-body body)
(funcall dump-last-value tmp-file
(member "pp" result-params))
(funcall send-wait) (funcall send-wait)
(insert org-babel-python-eoe-indicator)
(funcall send-wait)))
(org-babel-eval-read-file tmp-file))))))
(unless (string= (substring org-babel-python-eoe-indicator 1 -1) results)
(org-babel-result-cond result-params
results
(org-babel-python-table-or-string results)))))
(advice-add 'org-babel-python-evaluate-session :override 'my/org-babel-python-evaluate-session)
2 个赞
开始玩 ob-python 了,下一步考虑 ob-ipython,scimax 不?不如直接入 lpy 的坑吧
@twlz0ne
能提交PATCH到Org去么?Org接受少量行数的PATCH。行数多的话,只要签一个电子版PDF的FSF文档就行了。我签好,等了3天就好了。
2 个赞
great. 我提交patch经常这样,尤其是大的patch。中间修改好多次。毕竟不是高手。有几次心累,缓几天,再重新拿起来修改。