PythonCall.jl icon indicating copy to clipboard operation
PythonCall.jl copied to clipboard

print versus println to stdout

Open andrew-saydjari opened this issue 2 years ago • 7 comments

In transitioning from PyCall.jl, I was just trying to confirm that the stdout forwarding worked similarly and came across an example I found puzzling.

@py begin
    import numpy as np
    a = np.zeros(10)
    println(a)
end

Completes and prints as normal

@py begin
    import numpy as np
    a = np.zeros(10)
    print(a)
end

Fails and gives the error "Python: TypeError: memoryview: a bytes-like object is required, not 'str'".

I am just trying to reproduce the functionality I had before with py_str and using the pyimport("sys")."stdout" = PyTextIO(stdout). My concern is that sometimes I want to import and run python packages that are doing print and not println and would like that to work without me having to edit them. Is this expected behavior or have I done something wrong/there is a better way to be going about this?

Julia Version 1.8.2
Commit 36034abf260 (2022-09-29 15:21 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
[6099a3de] PythonCall v0.9.12

andrew-saydjari avatar Apr 08 '23 21:04 andrew-saydjari

I'm guessing you did something like this?

julia> pyimport("sys").stdout = stdout
Base.TTY(Base.Libc.WindowsRawSocket(0x0000000000000278) open, 0 bytes waiting)

julia> @py begin
           import numpy as np
           a = np.zeros(10)
           print(a)
       end
ERROR: Python: TypeError: memoryview: a bytes-like object is required, not 'str'

This occurs because when Julia's stdout is converted to a Python object, it by default becomes a binary IO object, which expects its inputs to be bytes not str. To get a text IO object instead, use pytextio:

julia> pyimport("sys").stdout = pytextio(stdout)
Python: Julia: Base.TTY(Base.Libc.WindowsRawSocket(0x0000000000000278) open, 0 bytes waiting)

julia> @py begin
           import numpy as np
           a = np.zeros(10)
           print(a)
       end
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

I'd advise against overriding sys.stdout though, there may be a cleaner way to do what you're doing.

cjdoris avatar Apr 24 '23 17:04 cjdoris

Yeah, I tried some variants of that. The suggestion you made works as you said. Thanks! But, I would be interested in finding a cleaner way as well. The only thing I am trying to do here is preserve the print statements internal to python packages that I am loading (that, without this hack, are not being printed below the code block that calls them). The forwarding of the python print statements to Julia stdout seems like it would be the expected (or at least desired) behavior.

andrew-saydjari avatar Apr 25 '23 03:04 andrew-saydjari

Stuff printed by Python code to stdout/stderr should still appear no problem. Are you running in some other environment which redirects stdout, such as Jupyter?

cjdoris avatar May 14 '23 13:05 cjdoris

Right, I should have said this is in the Jupyter context. This leads to some odd behavior with the recommending fix I mentioned solving the problem for PyCall.

andrew-saydjari avatar May 15 '23 04:05 andrew-saydjari

Ok yeah in Jupyter the only solution I'm aware of is to override stdout. PythonCall used to do this for you but got removed - maybe it could be readded with the new package extensions stuff.

cjdoris avatar May 15 '23 08:05 cjdoris

This issue has been marked as stale because it has been open for 30 days with no activity. If the issue is still relevant then please leave a comment, or else it will be closed in 7 days.

github-actions[bot] avatar Aug 25 '23 01:08 github-actions[bot]

This issue has been closed because it has been stale for 7 days. You can re-open it if it is still relevant.

github-actions[bot] avatar Sep 01 '23 01:09 github-actions[bot]