How to run Cython examples in SageMathCell

Hi, this is not a math question, this is a programming question.

I'm trying to run the first example at doc.sagemath.org/html/en/thematic_tutorials/cython_interface by using SageMathCell service (link).

For this, I've created a zip folder that I've stored in the cloud (Google Drive).

When I run the following python script in SageMathCell (I wrote it to test Cython capabilities in SageMath remote server), it seems good, but I can't see the output, that would be "Hello World".

This python script, after execution, ends with "Compiling ./Call_C_code/hello_sage.pyx..." without anyone else output.

Can you help me? Thanks,

import os
import tempfile
import sys
from distutils.dir_util import copy_tree

directory_name = tempfile.mkdtemp()
print(directory_name)
sys.path.append(directory_name)

import urllib
filename = "/Call_C_code.zip"
urllib.urlretrieve(url, directory_name + filename)

# opening the zip file in READ mode
from zipfile import ZipFile
os.chdir(directory_name)
file_name = "Call_C_code.zip"

with ZipFile(file_name, 'r') as zip:
# extracting all the files
print('Extracting all the files now...')
zip.extractall()
print('Done!')

print(sys.path)
print(os.getcwd())

for root, dirs, files in os.walk("."):
for filename in files:
print(filename)

#############
%runfile Call_C_code/hello_sage.pyx
my_bridge_function()

edit retag close merge delete

For what it's worth, I don't know why you're doing sys.path.append(directory_name), but you probably needn't do so. What does hello_sage.pyx have in it? You can also use %cython for directly compiling Cython code, but %runfile should effectively do the same if it's passed a path to a .pyx file.

( 2018-10-02 14:47:49 +0200 )edit

Hi @Iguananaut thanks, I use sys.path.append() to be sure the remote python environment can find my files and libraries to be compiled in the temporary folder. Why it is not necessary?

"hello_sage.pyx" is a file containing: """ cdef extern from "hello.c": void hello_world()

def my_bridge_function(): hello_world() # This is the C function from hello.c """ as this link suggests. The path for "hello_sage.pyx", I suppose, is directory_name/Call_C_code, as indicated in "%runfile Call_C_code/hello_sage.pyx" and with the command "os.chdir(directory_name)" I'm sure my working folder is the temporary folder named "directory_name".

What is wrong? Thank you

( 2018-10-03 16:03:40 +0200 )edit

FWIW you should be able to edit your question to add more details like the contents of the file.

I don't know what you mean by "the remote python environment". If you just want to run a single Python module it's not necessary to add its path to sys.path. sys.path only affects where modules are searched for when you use the import statement, wheres %runfile is already giving the path to a module directly.

This is like the difference in a shell when running a command by name like ls, as opposed to its full path /bin/ls. To run /bin/ls you don't need /bin on your PATH environment variable, but if you just run ls you do because the shell needs to know what paths to look in for a program called ls.

( 2018-10-08 11:11:03 +0200 )edit

Hi @Iguananaut thank you for support, I try to describe better what I mean. I use sage only on the Internet using the free service SageMathCell. It is an online sagemath service.

Inside the zip folder "Call_C_code.zip" there are 3 files, one of them (text.txt) is a dummy text file I added for some tests, the other two files are the files of the example here. The two files for Cython test are: "hello_sage.pyx" and "hello_test.c".

Inside "hello_sage.pyx" there is the Cython code, while inside "hello_test.c" there is the C code. The content is, adapted on filenames, the same you find here.

( 2018-10-08 12:29:11 +0200 )edit

Please can you run without problems the script in first post by using SageMathCell or not? I'm testing Cython features of the online service SageMathCell by following the simple example "How to call a C code (or a compiled library) from Sage?".

"hello_sage.pyx":

cdef extern from "Call_C_code/hello_test.c":
void hello_world()

def my_bridge_function():
hello_world() # This is the C function from hello_test.c


"hello_test.c":

#include <stdio.h>

void hello_world(){
printf("Hello World\n");
}


Thanks

( 2018-10-08 12:34:25 +0200 )edit

Sort by » oldest newest most voted

I'll attempt to recreate my original answer here; I'm not sure what happened to the old one. I tried your example code in SageMathCell and it works fine (as I previously suggested however there is no need for modifying sys.path).

The problem seems to have something to do with how SageMathCell handles standard output. I noticed this after trying: print(sys.__stdout__) in SMC, and that returns: <log.StdLog object at 0x7f68d71cbb50>.

I don't know exactly how SMC works, but that seems to indicate that Python's normal stdout is being replaced with some object that logs stdout at the Python level. However, when you compile C code containing printf()s, that outputs at the C level, but I suspect SMC is not capturing that, and is only capturing prints from Python by overriding sys.__stdout__. I would consider this a bug in SMC, as it should be able to capture output to the stdout file descriptor, but it appears it does not.

more

Hi @Iguananaut, thank you for testing it! Ok, I will try to contact the SageMathCell service to understand how to solve the problem.

For now I will try to perform some tests with C functions that are independent from the standard C input/output library.

( 2018-10-08 17:08:16 +0200 )edit