I'm having a tough time figuring out how to run NodeJS from Python. I have no problems running ShellScript from Python and NodeJS from ShellScript, but can't seem to get NodeJS from Python, I just get the following output:
b"
These are the simplified version of my scripts.
NodeJS I am trying to run from within Python.
#!/usr/bin/env node
console.log("Hello " + process.argv[2]);
And here is the Python, using Python3.
from datetime import datetime
import json
import os
import re
import sys
import subprocess
if __name__ == '__main__':
p = subprocess.Popen(['/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)
out = p.stdout.read()
print(out)
Thanks for the help! Much appreciated.
EDITS:
I have no issue executing the following from the commandline, as 'hello.js' is executable:
hello.js 'Brett'
shell=true does not fix it.
Additionally, I am on macOS Catalina 10.15.5 and therefore my shell is zsh.
If I add node to the front of the command, I get no such file or directory for node, I tried it as follows:
p = subprocess.Popen(['/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)
Thanks everyone for the responses. All were super helpful. Especially #max-stanley and #jared-smith.
The following ended up working for me:
p = subprocess.Popen(['/usr/local/bin/node', '/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)
out = p.stdout.read()
print(out)
Not sure why it doesn't work with the shebang in the executable js file but I am not committed to it, so I will just take the working solution and move on. ;-)
Cheers!
Okay after doing some testing based on the comments by Max Stanley:
There is an inconsistency between Linux and MacOS here about the population of the argv array. On Mac you will want the second index (1) and on Linux you will want the third (2).
I recommend using a command-line argument parser like command-line-args which should paper over the platform differences.
In the meantime you can specify node in the python subprocess call Popen(["node", "/Users/Brett/scripts/hello.js", "Brett"]) which has the same behavior on both.
Having tested this on my system, it looks as though you need to either make the hello.js file executable chmod +x ./hello.js or you need to add 'node' to the beginning of the Popen argument list as #Jared had said.
How can I play audio (it would be like a 1 second sound) from a Python script?
It would be best if it was platform independent, but firstly it needs to work on a Mac.
I know I could just execute the afplay file.mp3 command from within Python, but is it possible to do it in raw Python? I would also be better if it didn't rely on external libraries.
Your best bet is probably to use pygame/SDL. It's an external library, but it has great support across platforms.
pygame.mixer.init()
pygame.mixer.music.load("file.mp3")
pygame.mixer.music.play()
You can find more specific documentation about the audio mixer support in the pygame.mixer.music documentation
Try playsound which is a Pure Python, cross platform, single function module with no dependencies for playing sounds.
Install via pip:
$ pip install playsound
Once you've installed, you can use it like this:
from playsound import playsound
playsound('/path/to/a/sound/file/you/want/to/play.mp3')
Take a look at Simpleaudio, which is a relatively recent and lightweight library for this purpose:
> pip install simpleaudio
Then:
import simpleaudio as sa
wave_obj = sa.WaveObject.from_wave_file("path/to/file.wav")
play_obj = wave_obj.play()
play_obj.wait_done()
Make sure to use uncompressed 16 bit PCM files.
You can find information about Python audio here: http://wiki.python.org/moin/Audio/
It doesn't look like it can play .mp3 files without external libraries. You could either convert your .mp3 file to a .wav or other format, or use a library like PyMedia.
In pydub we've recently opted to use ffplay (via subprocess) from the ffmpeg suite of tools, which internally uses SDL.
It works for our purposes – mainly just making it easier to test the results of pydub code in interactive mode – but it has it's downsides, like causing a new program to appear in the dock on mac.
I've linked the implementation above, but a simplified version follows:
import subprocess
def play(audio_file_path):
subprocess.call(["ffplay", "-nodisp", "-autoexit", audio_file_path])
The -nodisp flag stops ffplay from showing a new window, and the -autoexit flag causes ffplay to exit and return a status code when the audio file is done playing.
edit: pydub now uses pyaudio for playback when it's installed and falls back to ffplay to avoid the downsides I mentioned. The link above shows that implementation as well.
Sorry for the late reply, but I think this is a good place to advertise my library ...
AFAIK, the standard library has only one module for playing audio: ossaudiodev.
Sadly, this only works on Linux and FreeBSD.
UPDATE: There is also winsound, but obviously this is also platform-specific.
For something more platform-independent, you'll need to use an external library.
My recommendation is the sounddevice module (but beware, I'm the author).
The package includes the pre-compiled PortAudio library for Mac OS X and Windows, and can be easily installed with:
pip install sounddevice --user
It can play back sound from NumPy arrays, but it can also use plain Python buffers (if NumPy is not available).
To play back a NumPy array, that's all you need (assuming that the audio data has a sampling frequency of 44100 Hz):
import sounddevice as sd
sd.play(myarray, 44100)
For more details, have a look at the documentation.
It cannot read/write sound files, you'll need a separate library for that.
Aaron's answer appears to be about 10x more complicated than necessary. Just do this if you only need an answer that works on OS X:
from AppKit import NSSound
sound = NSSound.alloc()
sound.initWithContentsOfFile_byReference_('/path/to/file.wav', True)
sound.play()
One thing... this returns immediately. So you might want to also do this, if you want the call to block until the sound finishes playing.
from time import sleep
sleep(sound.duration())
Edit: I took this function and combined it with variants for Windows and Linux. The result is a pure python, cross platform module with no dependencies called playsound. I've uploaded it to pypi.
pip install playsound
Then run it like this:
from playsound import playsound
playsound('/path/to/file.wav', block = False)
MP3 files also work on OS X. WAV should work on all platforms. I don't know what other combinations of platform/file format do or don't work - I haven't tried them yet.
You can see this: http://www.speech.kth.se/snack/
s = Sound()
s.read('sound.wav')
s.play()
It is possible to play audio in OS X without any 3rd party libraries using an analogue of the following code. The raw audio data can be input with wave_wave.writeframes. This code extracts 4 seconds of audio from the input file.
import wave
import io
from AppKit import NSSound
wave_output = io.BytesIO()
wave_shell = wave.open(wave_output, mode="wb")
file_path = 'SINE.WAV'
input_audio = wave.open(file_path)
input_audio_frames = input_audio.readframes(input_audio.getnframes())
wave_shell.setnchannels(input_audio.getnchannels())
wave_shell.setsampwidth(input_audio.getsampwidth())
wave_shell.setframerate(input_audio.getframerate())
seconds_multiplier = input_audio.getnchannels() * input_audio.getsampwidth() * input_audio.getframerate()
wave_shell.writeframes(input_audio_frames[second_multiplier:second_multiplier*5])
wave_shell.close()
wave_output.seek(0)
wave_data = wave_output.read()
audio_stream = NSSound.alloc()
audio_stream.initWithData_(wave_data)
audio_stream.play()
This is the easiest & best iv'e found. It supports Linux/pulseaudio, Mac/coreaudio, and Windows/WASAPI.
import soundfile as sf
import soundcard as sc
default_speaker = sc.default_speaker()
samples, samplerate = sf.read('bell.wav')
default_speaker.play(samples, samplerate=samplerate)
See https://github.com/bastibe/PySoundFile and https://github.com/bastibe/SoundCard for tons of other super-useful features.
Also on OSX - from SO, using OSX's afplay command:
import subprocess
subprocess.call(["afplay", "path/to/audio/file"])
UPDATE: All this does is specify how to do what the OP wanted to avoid doing in the first place. I guess I posted this here because what OP wanted to avoid was the info I was looking for. Whoops.
Install playsound package using :
pip install playsound
Usage:
from playsound import playsound
playsound("file location\audio.p3")
Try PySoundCard which uses PortAudio for playback which is available on many platforms.
In addition, it recognizes "professional" sound devices with lots of channels.
Here a small example from the Readme:
from pysoundcard import Stream
"""Loop back five seconds of audio data."""
fs = 44100
blocksize = 16
s = Stream(samplerate=fs, blocksize=blocksize)
s.start()
for n in range(int(fs*5/blocksize)):
s.write(s.read(blocksize))
s.stop()
Mac OS I tried a lot of codes but just this works on me
import pygame
import time
pygame.mixer.init()
pygame.init()
pygame.mixer.music.load('fire alarm sound.mp3') *On my project folder*
i = 0
while i<10:
pygame.mixer.music.play(loops=10, start=0.0)
time.sleep(10)*to protect from closing*
pygame.mixer.music.set_volume(10)
i = i + 1
It's Simple. I did it this way.
For a wav file
from IPython.display import Audio
from scipy.io.wavfile import read
fs, data = read('StarWars60.wav', mmap=True) # fs - sampling frequency
data = data.reshape(-1, 1)
Audio(data = data[:, 0], rate = fs)
For mp3 file
import IPython.display import Audio
Audio('audio_file_name.mp3')
Pypi has a list of modules for python in music. My favorite would be jython because it has more resources and libraries for music. As example of of code to play a single note from the textbook:
# playNote.py
# Demonstrates how to play a single note.
from music import * # import music library
note = Note(C4, HN) # create a middle C half note
Play.midi(note) # and play it!
To play a notification sound using python, call a music player, such as vlc. VLC prompted me to use its commandline version, cvlc, instead.
from subprocess import call
call(["cvlc", "--play-and-exit", "myNotificationTone.mp3"])
It requires vlc to be preinstalled on the device. Tested on Linux(Ubuntu 16.04 LTS); Running Python 3.5.
Try sounddevice
If you don't have the module enter
pip install sounddevice in your terminal.
Then in your preferred Python script (I use Juypter), enter
import sounddevice as sd
sd.play(audio, sr) will play what you want through Python
The best way to get the audio and samplerate you want is with the librosa module. Enter this in terminal if you don't have the librosa module.
pip install librosa
audio, sr = librosa.load('wave_file.wav')
Whatever wav file you want to play, just make sure it's in the same directory as your Python script. This should allow you to play your desired wav file through Python
Cheers,
Charlie
P.S.
Once audio is a "librosa" data object, Python sees it as a numpy array. As an experiment, try playing a long (try 20,000 data points) thing of a random numpy array. Python should play it as white noise. The sounddevice module plays numpy arrays and lists as well.
In a Colab notebook you can do:
from IPython.display import Audio
Audio(waveform, Rate=16000)
This library aims to be simple, cross-platform and have many features: https://github.com/libwinmedia/libwinmedia-py
It requires a libwinmedia shared library, which you can download in Releases tab.
You can install it using pip install libwinmedia
Example:
import libwinmedia
player = libwinmedia.Player(True)
player.set_position_callback(lambda position: print(f"{position} ms."))
media = libwinmedia.Media("test.mp3")
player.open(media)
This should work on Linux, Mac or Windows:
from preferredsoundplayer import *
soundplay("audio.wav")
Should work for mp3 also.
In Linux it will try up to 4 different methods. In Windows it uses winmm.dll. In Mac it uses afplay.
I wrote it because:
I kept having issues with cross-compatibility for playing sounds.
It also manually garbage collects calls to the winmm.dll player in Windows and appropriate closes finished sounds.
It has no dependencies, other than what comes with Windows 10, the standard Linux kernel, MacOS 10.5 or later, and the Python Standard Library.
You can install using pip install preferredsoundplayer (see project) or just utilize the source code which is a single file (source code) .
Put this at the top of your python script you are writing:
import subprocess
If the wav file IS in the directory of the python script:
f = './mySound.wav'
subprocess.Popen(['aplay','-q',f)
If the wav file IS NOT in the directory of the python script:
f = 'mySound.wav'
subprocess.Popen(['aplay','-q', 'wav/' + f)
If you want to learn more about aplay:
man aplay
I recently made my Music Player support all audio files locally. I did this by figuring out a way to use the vlc python module and also the VLC dll files.
You can check it out:
https://github.com/elibroftw/music-caster/blob/master/audio_player.py
For those who use Linux and the other packages haven't worked on MP3 files, audioplayer worked fine for me:
https://pypi.org/project/audioplayer/
from audioplayer import AudioPlayer
AudioPlayer("path/to/somemusic.mp3").play(block=True)
If you're on OSX, you can use the "os" module or "subprocess" etc. to call the OSX "play" command. From the OSX shell, it looks like
play "bah.wav"
It starts to play in about a half-second on my machine.
Simply You can do it with the help of cvlc-
I did it in this way:
import os
os.popen2("cvlc /home/maulo/selfProject/task.mp3 --play-and-exit")
/home/maulo/selfProject/task.mp3. This is the location of my mp3 file.
with the help of "--play-and-exit" you will be able to play again the sound without ending the vlc process.
If I run this in python under linux it works:
start = "\033[1;31m"
end = "\033[0;0m"
print "File is: " + start + "<placeholder>" + end
But if I run it in Windows it doesn't work, how can I make the ANSI escape codes work also on Windows?
For windows, calling os.system("") makes the ANSI escape sequence get processed correctly:
import os
os.system("") # enables ansi escape characters in terminal
COLOR = {
"HEADER": "\033[95m",
"BLUE": "\033[94m",
"GREEN": "\033[92m",
"RED": "\033[91m",
"ENDC": "\033[0m",
}
print(COLOR["GREEN"], "Testing Green!!", COLOR["ENDC"])
Here is the solution I have long sought. Simply use the ctypes module, from the standard library. It is installed by default with Python 3.x, only on Windows. So check if the OS is Windows before to use it (with platform.system, for example).
import os
if os.name == 'nt': # Only if we are running on Windows
from ctypes import windll
k = windll.kernel32
k.SetConsoleMode(k.GetStdHandle(-11), 7)
After you have done that, you can use ASCII special characters (like \x1b[31m, for red color) as if you were on a Unix operating system :
message = "ERROR"
print(f"\x1b[31m{message}\x1b[0m")
I like this solution because it does not need to install a module (like colorama or termcolor).
You could check Python module to enable ANSI colors for stdout on Windows? to see if it's useful.
The colorama module seems to be cross-platform.
You install colorama:
pip install colorama
Then:
import colorama
colorama.init()
start = "\033[1;31m"
end = "\033[0;0m"
print "File is: " + start + "<placeholder>" + end
If you are on Win 10 (with native ANSI support in cmd) there seems to be a bug which was marked as resolved in Python 3.7 (though it doesn't look it was actually fixed).
One workaround is to add subprocess.call('', shell=True) before printing.
You could take a look at https://github.com/kennethreitz/clint
From the readme:
>>> from clint.textui import colored, puts
>>> puts(colored.red('red text'))
red text
# It's red in Windows, OSX, and Linux alike.
You can just do this:
import os
os.system("")
This works for me. Command prompt does support color by default.
Sending the ANSI escape sequences should work, according to thousands of fine answers on the internet, but one obscure detail took me two half days to stumble upon. The trick is that a certain registry key must be set. I'm using (just for today) Windows 10 Enterprise, version 1709, build 16299.
In HKEY_CURRENT_USER, under Console, right between TrimLeadingZeros and WindowAlpha there should be VirtualTerminalLevel. If it doesn't exist, go ahead and create it. It's a REG_DWORD. Set its value to 1. Open a new terminal, run Python, and have a bit o' fun.
print("\033[48;2;255;140;60m ORANGE BACKGROUND \033[48;2;0;0;0m")
See https://github.com/ytdl-org/youtube-dl/issues/15758 to read stuff by people who know more than I do about this.
Now if I could remember why I wanted to colorize my Python program's output...
Here is a bit simpler code I have used.
import os
os.system("color") # Alternative - os.system("")
TCOLOR = "\033[31;3m"
ENDC = "\033[m"
print (TCOLOR + "Make yourself happy" + ENDC)
I wrote a simple module, available at: http://pypi.python.org/pypi/colorconsole
It works with Windows, Mac OS X and Linux. It uses ANSI for Linux and Mac, but native calls to console functions on Windows. You have colors, cursor positioning and keyboard input. It is not a replacement for curses, but can be very useful if you need to use in simple scripts or ASCII games.
The docs can be found here: http://code.google.com/p/colorconsole/wiki/PageName
PS: This is the same answer for Print in terminal with colors using Python?, but I didn't know how to link to a reply.
Try adding a semi-colon here \033[;, I get undesirable effects without that semi-colon.
start = "\033[;1;31m"
end = "\033[;0;0m"
import os
os.system("")
COR = {
"HEADER": "\033[95m",
"BLUE": "\033[94m",
"GREEN": "\033[92m",
"RED": "\033[91m",
"ENDC": "\033[0m",
}
print(COR["RED"]+"Testing Green!!"+COR["ENDC"])
Using only the modules that come with a standard python 2.6 installation, would it be possible to play a simple beeping noise?
If you're on a Unix terminal, you can print "\a" to get a terminal bell:
>>> def beep():
... print "\a"
>>> beep()
Of course, that will print a newline too… So sys.stdout.write("\a") might be better. But you get the idea.
On windows:
import winsound # for sound
import time # for sleep
winsound.Beep(440, 250) # frequency, duration
time.sleep(0.25) # in seconds (0.25 is 250ms)
winsound.Beep(600, 250)
time.sleep(0.25)
34.4. winsound — Sound-playing interface for Windows:
http://docs.python.org/2.6/search.html?q=sound&check_keywords=yes&area=default
See also:
Clear screen and beep for various platforms. (Python recipe)
http://code.activestate.com/recipes/577588-clear-screen-and-beep-for-various-platforms/
On Android with QPython this is how it goes:
import androidhelper
droid=androidhelper.Android()
droid.generateDtmfTones('0',100)
This will place a beep of a certain frequency for certain time.